Beispiel #1
0
        /// <summary>
        /// Called when a set is attempting to assign to a field or property from a derived class through the base class.
        ///
        /// The default behavior is to allow the assignment.
        /// </summary>
        public virtual ErrorInfo MakeStaticAssignFromDerivedTypeError(Type accessingType, DynamicMetaObject self, MemberTracker assigning, DynamicMetaObject assignedValue, OverloadResolverFactory context)
        {
            switch (assigning.MemberType)
            {
            case TrackerTypes.Property:
                PropertyTracker pt     = (PropertyTracker)assigning;
                MethodInfo      setter = pt.GetSetMethod() ?? pt.GetSetMethod(true);
                return(ErrorInfo.FromValueNoError(
                           AstUtils.SimpleCallHelper(
                               setter,
                               ConvertExpression(
                                   assignedValue.Expression,
                                   setter.GetParameters()[0].ParameterType,
                                   ConversionResultKind.ExplicitCast,
                                   context
                                   )
                               )
                           ));

            case TrackerTypes.Field:
                FieldTracker ft = (FieldTracker)assigning;
                return(ErrorInfo.FromValueNoError(
                           Expression.Assign(
                               Expression.Field(null, ft.Field),
                               ConvertExpression(assignedValue.Expression, ft.FieldType, ConversionResultKind.ExplicitCast, context)
                               )
                           ));

            default:
                throw new InvalidOperationException();
            }
        }
Beispiel #2
0
        private Expression GenDlrForMethod(GenContext context)
        {
            Expression target = _target.GenDlr(context);

            Expression[] args = GenTypedArgs(context, _method.GetParameters(), _args);

            return(AstUtils.SimpleCallHelper(target, _method, args));;
        }
Beispiel #3
0
 /// <summary>
 ///   Helper to produce a conversion rule by calling the method to do the convert.  This version takes the parameter
 ///   to be passed to the conversion function and we call it w/ our own value or w/ our Extensible.Value.
 /// </summary>
 private static MSAst MakeConversionTargetWorker(
     ConversionResultKind kind, MethodTracker method, bool isImplicit, MSAst param)
 {
     return(WrapForThrowingTry(
                kind,
                isImplicit,
                AstUtils.SimpleCallHelper(
                    method.Method,
                    param
                    ),
                method.Method.ReturnType));
 }
 /// <summary>
 /// Helper to produce a conversion rule by calling the method to do the convert.  This version takes the parameter
 /// to be passed to the conversion function and we call it w/ our own value or w/ our Extensible.Value.
 /// </summary>
 private static DynamicMetaObject MakeConversionTargetWorker(ConversionResultKind kind, MethodTracker method, bool isImplicit, BindingRestrictions restrictions, Expression param)
 {
     return(new DynamicMetaObject(
                WrapForThrowingTry(
                    kind,
                    isImplicit,
                    AstUtils.SimpleCallHelper(
                        method.Method,
                        param
                        ),
                    method.Method.ReturnType
                    ),
                restrictions
                ));
 }
Beispiel #5
0
        /// <summary>
        /// Builds an expression for a call to the provided method using the given expressions.  If the
        /// method is not static the first parameter is used for the instance.
        ///
        /// Parameters are converted using the binder's conversion rules.
        ///
        /// If an incorrect number of parameters is provided MakeCallExpression returns null.
        /// </summary>
        public Expression MakeCallExpression(Expression context, MethodInfo method, IList <Expression> parameters)
        {
            ParameterInfo[] infos = method.GetParameters();
            Expression      callInst = null;
            int             parameter = 0, startArg = 0;

            Expression[] callArgs = new Expression[infos.Length];

            if (!method.IsStatic)
            {
                callInst  = AstUtils.Convert(parameters[0], method.DeclaringType);
                parameter = 1;
            }
            if (infos.Length > 0 && typeof(CodeContext).IsAssignableFrom(infos[0].ParameterType))
            {
                startArg    = 1;
                callArgs[0] = context;
            }

            for (int arg = startArg; arg < infos.Length; arg++)
            {
                if (parameter < parameters.Count)
                {
                    callArgs[arg] = ConvertExpression(
                        parameters[parameter++],
                        infos[arg].ParameterType,
                        ConversionResultKind.ExplicitCast,
                        context
                        );
                }
                else
                {
                    return(null);
                }
            }

            // check that we used all parameters
            if (parameter != parameters.Count)
            {
                return(null);
            }

            return(AstUtils.SimpleCallHelper(callInst, method, callArgs));
        }
        private void MakePropertyRule(SetOrDeleteMemberInfo memInfo, DynamicMetaObject instance, DynamicMetaObject target, Type targetType, MemberGroup properties, DynamicMetaObject errorSuggestion)
        {
            PropertyTracker info = (PropertyTracker)properties[0];

            MethodInfo setter = info.GetSetMethod(true);

            // Allow access to protected getters TODO: this should go, it supports IronPython semantics.
            if (setter != null && !setter.IsPublic && !setter.IsProtected())
            {
                if (!PrivateBinding)
                {
                    setter = null;
                }
            }

            if (setter != null)
            {
                // TODO (tomat): this used to use setter.ReflectedType, is it still correct?
                setter = CompilerHelpers.TryGetCallableMethod(targetType, setter);

                if (!PrivateBinding && !CompilerHelpers.IsVisible(setter))
                {
                    setter = null;
                }
            }

            if (setter != null)
            {
                if (info.IsStatic != (instance == null))
                {
                    memInfo.Body.FinishError(
                        errorSuggestion ?? MakeError(
                            MakeStaticPropertyInstanceAccessError(
                                info,
                                true,
                                instance,
                                target
                                ),
                            typeof(object)
                            )
                        );
                }
                else if (info.IsStatic && info.DeclaringType != targetType)
                {
                    memInfo.Body.FinishError(
                        errorSuggestion ?? MakeError(
                            MakeStaticAssignFromDerivedTypeError(targetType, instance, info, target, memInfo.ResolutionFactory),
                            typeof(object)
                            )
                        );
                }
                else if (setter.ContainsGenericParameters)
                {
                    memInfo.Body.FinishCondition(
                        MakeGenericPropertyExpression(memInfo)
                        );
                }
                else if (setter.IsPublic && !setter.DeclaringType.IsValueType())
                {
                    if (instance == null)
                    {
                        memInfo.Body.FinishCondition(
                            Ast.Block(
                                AstUtils.SimpleCallHelper(
                                    setter,
                                    ConvertExpression(
                                        target.Expression,
                                        setter.GetParameters()[0].ParameterType,
                                        ConversionResultKind.ExplicitCast,
                                        memInfo.ResolutionFactory
                                        )
                                    ),
                                Ast.Constant(null)
                                )
                            );
                    }
                    else
                    {
                        memInfo.Body.FinishCondition(
                            MakeReturnValue(
                                MakeCallExpression(memInfo.ResolutionFactory, setter, instance, target),
                                target
                                )
                            );
                    }
                }
                else
                {
                    // TODO: Should be able to do better w/ value types.
                    memInfo.Body.FinishCondition(
                        MakeReturnValue(
                            Ast.Call(
                                AstUtils.Constant(((ReflectedPropertyTracker)info).Property), // TODO: Private binding on extension properties
                                typeof(PropertyInfo).GetMethod("SetValue", new Type[] { typeof(object), typeof(object), typeof(object[]) }),
                                instance == null ? AstUtils.Constant(null) : AstUtils.Convert(instance.Expression, typeof(object)),
                                AstUtils.Convert(
                                    ConvertExpression(
                                        target.Expression,
                                        setter.GetParameters()[0].ParameterType,
                                        ConversionResultKind.ExplicitCast,
                                        memInfo.ResolutionFactory
                                        ),
                                    typeof(object)
                                    ),
                                Ast.NewArrayInit(typeof(object))
                                ),
                            target
                            )
                        );
                }
            }
            else
            {
                memInfo.Body.FinishError(
                    errorSuggestion ?? MakeError(
                        MakeMissingMemberErrorForAssignReadOnlyProperty(targetType, instance, memInfo.Name), typeof(object)
                        )
                    );
            }
        }
Beispiel #7
0
        internal Expression MakeExpression(RestrictedArguments restrictedArgs)
        {
            bool[]       usageMarkers;
            Expression[] spilledArgs;
            Expression[] callArgs = GetArgumentExpressions(restrictedArgs, out usageMarkers, out spilledArgs);

            Expression call;
            MethodBase mb = _overload.ReflectionInfo;

            // TODO: make MakeExpression virtual on OverloadInfo?
            if (mb == null)
            {
                throw new InvalidOperationException("Cannot generate an expression for an overload w/o MethodBase");
            }

            MethodInfo mi = mb as MethodInfo;

            if (mi != null)
            {
                Expression instance;
                if (mi.IsStatic)
                {
                    instance = null;
                }
                else
                {
                    Debug.Assert(mi != null);
                    instance = _instanceBuilder.ToExpression(ref mi, _resolver, restrictedArgs, usageMarkers);
                    Debug.Assert(instance != null, "Can't skip instance expression");
                }

                if (CompilerHelpers.IsVisible(mi))
                {
                    call = AstUtils.SimpleCallHelper(instance, mi, callArgs);
                }
                else
                {
                    call = Ast.Call(
                        typeof(BinderOps).GetMethod("InvokeMethod"),
                        AstUtils.Constant(mi),
                        instance != null ? AstUtils.Convert(instance, typeof(object)) : AstUtils.Constant(null),
                        AstUtils.NewArrayHelper(typeof(object), callArgs)
                        );
                }
            }
            else
            {
                ConstructorInfo ci = (ConstructorInfo)mb;
                if (CompilerHelpers.IsVisible(ci))
                {
                    call = AstUtils.SimpleNewHelper(ci, callArgs);
                }
                else
                {
                    call = Ast.Call(
                        typeof(BinderOps).GetMethod("InvokeConstructor"),
                        AstUtils.Constant(ci),
                        AstUtils.NewArrayHelper(typeof(object), callArgs)
                        );
                }
            }

            if (spilledArgs != null)
            {
                call = Expression.Block(spilledArgs.AddLast(call));
            }

            Expression ret = _returnBuilder.ToExpression(_resolver, _argBuilders, restrictedArgs, call);

            List <Expression> updates = null;

            for (int i = 0; i < _argBuilders.Count; i++)
            {
                Expression next = _argBuilders[i].UpdateFromReturn(_resolver, restrictedArgs);
                if (next != null)
                {
                    if (updates == null)
                    {
                        updates = new List <Expression>();
                    }
                    updates.Add(next);
                }
            }

            if (updates != null)
            {
                if (ret.Type != typeof(void))
                {
                    ParameterExpression temp = Ast.Variable(ret.Type, "$ret");
                    updates.Insert(0, Ast.Assign(temp, ret));
                    updates.Add(temp);
                    ret = Ast.Block(new[] { temp }, updates.ToArray());
                }
                else
                {
                    updates.Insert(0, ret);
                    ret = Ast.Block(typeof(void), updates.ToArray());
                }
            }

            if (_resolver.Temps != null)
            {
                ret = Ast.Block(_resolver.Temps, ret);
            }

            return(ret);
        }
Beispiel #8
0
        internal Expression MakeExpression(ParameterBinder parameterBinder, IList <Expression> parameters)
        {
            bool[]       usageMarkers;
            Expression[] spilledArgs;
            Expression[] args = GetArgumentExpressions(parameterBinder, parameters, out usageMarkers, out spilledArgs);

            MethodBase mb = Method;
            MethodInfo mi = mb as MethodInfo;
            Expression ret, call;

            if (!mb.IsPublic || (mb.DeclaringType != null && !mb.DeclaringType.IsVisible))
            {
                if (mi != null)
                {
                    mi = CompilerHelpers.GetCallableMethod(mi, _binder._binder.PrivateBinding);
                    if (mi != null)
                    {
                        mb = mi;
                    }
                }
            }

            ConstructorInfo ci = mb as ConstructorInfo;

            Debug.Assert(mi != null || ci != null);
            if (mb.IsPublic && (mb.DeclaringType == null || mb.DeclaringType.IsVisible))
            {
                // public method
                if (mi != null)
                {
                    Expression instance = mi.IsStatic ? null : _instanceBuilder.ToExpression(parameterBinder, parameters, usageMarkers);
                    call = AstUtils.SimpleCallHelper(instance, mi, args);
                }
                else
                {
                    call = AstUtils.SimpleNewHelper(ci, args);
                }
            }
            else
            {
                // Private binding, invoke via reflection
                if (mi != null)
                {
                    Expression instance = mi.IsStatic ? Ast.Constant(null) : _instanceBuilder.ToExpression(parameterBinder, parameters, usageMarkers);
                    Debug.Assert(instance != null, "Can't skip instance expression");

                    call = Ast.Call(
                        typeof(BinderOps).GetMethod("InvokeMethod"),
                        Ast.Constant(mi),
                        AstUtils.Convert(instance, typeof(object)),
                        AstUtils.NewArrayHelper(typeof(object), args)
                        );
                }
                else
                {
                    call = Ast.Call(
                        typeof(BinderOps).GetMethod("InvokeConstructor"),
                        Ast.Constant(ci),
                        AstUtils.NewArrayHelper(typeof(object), args)
                        );
                }
            }

            if (spilledArgs != null)
            {
                call = Expression.Block(spilledArgs.AddLast(call));
            }

            ret = _returnBuilder.ToExpression(parameterBinder, _argBuilders, parameters, call);

            List <Expression> updates = null;

            for (int i = 0; i < _argBuilders.Count; i++)
            {
                Expression next = _argBuilders[i].UpdateFromReturn(parameterBinder, parameters);
                if (next != null)
                {
                    if (updates == null)
                    {
                        updates = new List <Expression>();
                    }
                    updates.Add(next);
                }
            }

            if (updates != null)
            {
                if (ret.Type != typeof(void))
                {
                    ParameterExpression temp = Ast.Variable(ret.Type, "$ret");
                    updates.Insert(0, Ast.Assign(temp, ret));
                    updates.Add(temp);
                    ret = Ast.Block(new [] { temp }, updates.ToArray());
                }
                else
                {
                    updates.Insert(0, ret);
                    ret = Ast.Convert(
                        Ast.Block(updates.ToArray()),
                        typeof(void)
                        );
                }
            }

            if (parameterBinder.Temps != null)
            {
                ret = Ast.Block(parameterBinder.Temps, ret);
            }

            return(ret);
        }