private DynamicMetaObject MakeDeleteMemberTarget(SetOrDeleteMemberInfo delInfo, DynamicMetaObject target, DynamicMetaObject errorSuggestion) {
            Type type = target.GetLimitType();
            BindingRestrictions restrictions = target.Restrictions;
            DynamicMetaObject self = target;

            if (typeof(TypeTracker).IsAssignableFrom(type)) {
                restrictions = restrictions.Merge(
                    BindingRestrictions.GetInstanceRestriction(target.Expression, target.Value)
                );

                type = ((TypeTracker)target.Value).Type;
                self = null;
            }

            delInfo.Body.Restrictions = restrictions;

            if (self == null || !MakeOperatorDeleteMemberBody(delInfo, self, type, "DeleteMember")) {
                MemberGroup group = GetMember(MemberRequestKind.Delete, type, delInfo.Name);
                if (group.Count != 0) {
                    if (group[0].MemberType == TrackerTypes.Property) {
                        MethodInfo del = ((PropertyTracker)group[0]).GetDeleteMethod(PrivateBinding);
                        if (del != null) {
                            MakePropertyDeleteStatement(delInfo, self, del);
                            return delInfo.Body.GetMetaObject(target);
                        }
                    }

                    delInfo.Body.FinishCondition(errorSuggestion ?? MakeError(MakeUndeletableMemberError(GetDeclaringMemberType(group), delInfo.Name), typeof(void)));
                } else {
                    delInfo.Body.FinishCondition(errorSuggestion ?? MakeError(MakeMissingMemberErrorForDelete(type, self, delInfo.Name), typeof(void)));
                }
            }

            return delInfo.Body.GetMetaObject(target);
        }
        private void MakeSetMemberRule(SetOrDeleteMemberInfo memInfo, Type type, DynamicMetaObject self, DynamicMetaObject value) {
            if (MakeOperatorSetMemberBody(memInfo, self, value, type, "SetMember")) {
                return;
            }


            MemberGroup members = GetMember(MemberRequestKind.Set, type, memInfo.Name);

            // if lookup failed try the strong-box type if available.
            if (self != null && members.Count == 0 && typeof(IStrongBox).IsAssignableFrom(type)) {
                self = new DynamicMetaObject(Ast.Field(AstUtils.Convert(self.Expression, type), type.GetField("Value")), BindingRestrictions.Empty, ((IStrongBox)self.Value).Value);
                type = type.GetGenericArguments()[0];

                members = GetMember(MemberRequestKind.Set, type, memInfo.Name);
            }

            Expression error;
            TrackerTypes memberTypes = GetMemberType(members, out error);
            if (error == null) {
                switch (memberTypes) {
                    case TrackerTypes.Method:
                    case TrackerTypes.TypeGroup:
                    case TrackerTypes.Type:
                    case TrackerTypes.Constructor:
                        memInfo.Body.FinishCondition(
                            MakeError(MakeReadOnlyMemberError(type, memInfo.Name), BindingRestrictions.Empty, typeof(object))
                        );
                        break;
                    case TrackerTypes.Event:
                        memInfo.Body.FinishCondition(
                            MakeError(MakeEventValidation(members, self, value, memInfo.ResolutionFactory), BindingRestrictions.Empty, typeof(object))
                        );
                        break;
                    case TrackerTypes.Field:
                        MakeFieldRule(memInfo, self, value, type, members);
                        break;
                    case TrackerTypes.Property:
                        MakePropertyRule(memInfo, self, value, type, members);
                        break;
                    case TrackerTypes.Custom:
                        MakeGenericBody(memInfo, self, value, type, members[0]);
                        break;
                    case TrackerTypes.All:
                        // no match
                        if (MakeOperatorSetMemberBody(memInfo, self, value, type, "SetMemberAfter")) {
                            return;
                        }

                        memInfo.Body.FinishCondition(
                            MakeError(MakeMissingMemberErrorForAssign(type, self, memInfo.Name), BindingRestrictions.Empty, typeof(object))
                        );
                        break;
                    default:
                        throw new InvalidOperationException();
                }
            } else {
                memInfo.Body.FinishCondition(error);
            }
        }
        private DynamicMetaObject MakeDeleteMemberTarget(SetOrDeleteMemberInfo delInfo, DynamicMetaObject target) {
            Type type = target.GetLimitType();
            BindingRestrictions restrictions = target.Restrictions;
            Expression self = target.Expression;

            // needed for DeleteMember call until DynamicAction goes away
            OldDynamicAction act = OldDeleteMemberAction.Make(
                this,
                delInfo.Name
            );

            if (typeof(TypeTracker).IsAssignableFrom(type)) {
                restrictions = restrictions.Merge(
                    BindingRestrictions.GetInstanceRestriction(target.Expression, target.Value)
                );

                type = ((TypeTracker)target.Value).Type;
                self = null;
            }

            delInfo.Body.Restrictions = restrictions;

            if (self == null || !MakeOperatorDeleteMemberBody(delInfo, self, type, "DeleteMember")) {
                MemberGroup group = GetMember(act, type, delInfo.Name);
                if (group.Count != 0) {
                    if (group[0].MemberType == TrackerTypes.Property) {
                        MethodInfo del = ((PropertyTracker)group[0]).GetDeleteMethod(PrivateBinding);
                        if (del != null) {
                            MakePropertyDeleteStatement(delInfo, self, del);
                            return delInfo.Body.GetMetaObject(target);
                        }
                    }

                    delInfo.Body.FinishCondition(MakeError(MakeUndeletableMemberError(GetDeclaringMemberType(group), delInfo.Name)));
                } else {
                    delInfo.Body.FinishCondition(MakeError(MakeMissingMemberError(type, delInfo.Name)));
                }
            }

            return delInfo.Body.GetMetaObject(target);
        }
        private DynamicMetaObject MakeSetMemberTarget(SetOrDeleteMemberInfo memInfo, DynamicMetaObject target, DynamicMetaObject value) {
            Type type = target.GetLimitType();
            Expression self = target.Expression;
            
            target = target.Restrict(target.GetLimitType());

            memInfo.Body.Restrictions = target.Restrictions;

            if (typeof(TypeTracker).IsAssignableFrom(type)) {
                type = ((TypeTracker)target.Value).Type;
                self = null;

                memInfo.Body.Restrictions = memInfo.Body.Restrictions.Merge(
                    BindingRestrictions.GetInstanceRestriction(target.Expression, target.Value)
                );
            }

            MakeSetMemberRule(memInfo, type, self, value);

            return memInfo.Body.GetMetaObject(target, value);
        }
        private void MakeFieldRule(SetOrDeleteMemberInfo memInfo, Expression instance, DynamicMetaObject target, Type targetType, MemberGroup fields) {
            FieldTracker field = (FieldTracker)fields[0];

            // TODO: Tmp variable for target
            if (field.DeclaringType.IsGenericType && field.DeclaringType.GetGenericTypeDefinition() == typeof(StrongBox<>)) {
                // work around a CLR bug where we can't access generic fields from dynamic methods.
                Type[] generic = field.DeclaringType.GetGenericArguments();
                memInfo.Body.FinishCondition(
                    MakeReturnValue(
                        Ast.Assign(
                            Ast.Field(
                                AstUtils.Convert(instance, field.DeclaringType),
                                field.DeclaringType.GetField("Value")
                            ),
                            AstUtils.Convert(target.Expression, generic[0])
                        ),
                        target
                    )
                );
            } else if (field.IsInitOnly || field.IsLiteral) {
                memInfo.Body.FinishCondition(
                    MakeError(
                        MakeReadOnlyMemberError(targetType, memInfo.Name), 
                        typeof(object)
                    )
                );
            } else if (field.IsStatic && targetType != field.DeclaringType) {
                memInfo.Body.FinishCondition(
                    MakeError(
                        MakeStaticAssignFromDerivedTypeError(targetType, field, target.Expression, memInfo.CodeContext), 
                        typeof(object)
                    )
                );
            } else if (field.DeclaringType.IsValueType && !field.IsStatic) {
                memInfo.Body.FinishCondition(
                    Ast.Throw(
                        Ast.New(
                            typeof(ArgumentException).GetConstructor(new Type[] { typeof(string) }),
                            AstUtils.Constant("cannot assign to value types")
                        ),
                        typeof(object)
                    )
                );
            } else if (field.IsPublic && field.DeclaringType.IsVisible) {
                memInfo.Body.FinishCondition(
                    MakeReturnValue(
                        Ast.Assign(
                            Ast.Field(
                                field.IsStatic ?
                                    null :
                                    AstUtils.Convert(instance, field.DeclaringType),
                                field.Field
                            ),
                            ConvertExpression(target.Expression, field.FieldType, ConversionResultKind.ExplicitCast, memInfo.CodeContext)
                        ),
                        target
                    )
                );
            } else {
                memInfo.Body.FinishCondition(
                    MakeReturnValue(
                        Ast.Call(
                            AstUtils.Convert(AstUtils.Constant(field.Field), typeof(FieldInfo)),
                            typeof(FieldInfo).GetMethod("SetValue", new Type[] { typeof(object), typeof(object) }),
                            field.IsStatic ?
                                AstUtils.Constant(null) :
                                (Expression)AstUtils.Convert(instance, typeof(object)),
                            AstUtils.Convert(target.Expression, typeof(object))
                        ),
                        target
                    )
                );
            }
        }
        /// <summary> if a member-injector is defined-on or registered-for this type call it </summary>
        private bool MakeOperatorSetMemberBody(SetOrDeleteMemberInfo memInfo, Expression self, DynamicMetaObject target, Type type, string name) {
            if (self != null) {
                MethodInfo setMem = GetMethod(type, name);
                if (setMem != null && setMem.IsSpecialName) {
                    ParameterExpression tmp = Ast.Variable(target.Expression.Type, "setValue");
                    memInfo.Body.AddVariable(tmp);

                    Expression call = MakeCallExpression(memInfo.CodeContext, setMem, AstUtils.Convert(self, type), AstUtils.Constant(memInfo.Name), tmp);

                    call = Ast.Block(Ast.Assign(tmp, target.Expression), call);

                    if (setMem.ReturnType == typeof(bool)) {
                        memInfo.Body.AddCondition(
                            call,
                            tmp
                        );
                    } else {
                        memInfo.Body.FinishCondition(Ast.Block(call, AstUtils.Convert(tmp, typeof(object))));
                    }

                    return setMem.ReturnType != typeof(bool);
                }
            }

            return false;
        }
        private void MakeGenericBody(SetOrDeleteMemberInfo memInfo, Expression instance, DynamicMetaObject target, Type type, MemberTracker tracker) {
            if (instance != null) {
                tracker = tracker.BindToInstance(instance);
            }

            Expression val = tracker.SetValue(memInfo.CodeContext, this, type, target.Expression);

            if (val != null) {
                memInfo.Body.FinishCondition(val);
            } else {
                memInfo.Body.FinishCondition(
                    MakeError(tracker.GetError(this), typeof(object))
                );
            }
        }
        private void MakePropertyRule(SetOrDeleteMemberInfo memInfo, Expression instance, DynamicMetaObject target, Type targetType, MemberGroup properties) {
            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) {
                setter = CompilerHelpers.GetCallableMethod(setter, PrivateBinding);

                if (info.IsStatic != (instance == null)) {
                    memInfo.Body.FinishCondition(
                        MakeError(
                            MakeStaticPropertyInstanceAccessError(
                                info,
                                true,
                                instance,
                                target.Expression
                            ), 
                            typeof(object)
                        )
                    );
                } else if (info.IsStatic && info.DeclaringType != targetType) {
                    memInfo.Body.FinishCondition(
                        MakeError(
                            MakeStaticAssignFromDerivedTypeError(targetType, info, target.Expression, memInfo.CodeContext), 
                            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.CodeContext
                                    )
                                ),
                                Ast.Constant(null)
                            )
                        );
                    } else {
                        memInfo.Body.FinishCondition(
                            MakeReturnValue(
                                MakeCallExpression(memInfo.CodeContext, setter, instance, target.Expression),
                                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, typeof(object)),
                                AstUtils.Convert(
                                    ConvertExpression(
                                        target.Expression,
                                        setter.GetParameters()[0].ParameterType,
                                        ConversionResultKind.ExplicitCast,
                                        memInfo.CodeContext
                                    ),
                                    typeof(object)
                                ),
                                Ast.NewArrayInit(typeof(object))
                            ),
                            target
                        )
                    );
                }
            } else {
                memInfo.Body.FinishCondition(
                    MakeError(
                        MakeMissingMemberError(targetType, memInfo.Name), typeof(object)
                    )
                );
            }
        }
 private void MakePropertyDeleteStatement(SetOrDeleteMemberInfo delInfo, DynamicMetaObject instance, MethodInfo delete) {
     delInfo.Body.FinishCondition(
         instance == null ? 
             MakeCallExpression(delInfo.ResolutionFactory, delete) :
             MakeCallExpression(delInfo.ResolutionFactory, delete, instance)
     );
 }
        private void MakeSetMemberRule(SetOrDeleteMemberInfo memInfo, Type type, Expression self, DynamicMetaObject target) {
            if (MakeOperatorSetMemberBody(memInfo, self, target, type, "SetMember")) {
                return;
            }

            // needed for GetMember call until DynamicAction goes away
            OldDynamicAction act = OldSetMemberAction.Make(
                this,
                memInfo.Name
            );

            MemberGroup members = GetMember(act, type, memInfo.Name);

            // if lookup failed try the strong-box type if available.
            if (members.Count == 0 && typeof(IStrongBox).IsAssignableFrom(type)) {
                self = Ast.Field(AstUtils.Convert(self, type), type.GetField("Value"));
                type = type.GetGenericArguments()[0];

                members = GetMember(act, type, memInfo.Name);
            }

            Expression error;
            TrackerTypes memberTypes = GetMemberType(members, out error);
            if (error == null) {
                switch (memberTypes) {
                    case TrackerTypes.Method:
                    case TrackerTypes.TypeGroup:
                    case TrackerTypes.Type:
                    case TrackerTypes.Constructor:
                        memInfo.Body.FinishCondition(
                            MakeError(MakeReadOnlyMemberError(type, memInfo.Name), typeof(object))
                        );
                        break;
                    case TrackerTypes.Event:
                        memInfo.Body.FinishCondition(
                            MakeError(MakeEventValidation(members, self, target.Expression, memInfo.CodeContext), typeof(object))
                        );
                        break;
                    case TrackerTypes.Field:
                        MakeFieldRule(memInfo, self, target, type, members);
                        break;
                    case TrackerTypes.Property:
                        MakePropertyRule(memInfo, self, target, type, members);
                        break;
                    case TrackerTypes.Custom:
                        MakeGenericBody(memInfo, self, target, type, members[0]);
                        break;
                    case TrackerTypes.All:
                        // no match
                        if (MakeOperatorSetMemberBody(memInfo, self, target, type, "SetMemberAfter")) {
                            return;
                        }

                        memInfo.Body.FinishCondition(
                            MakeError(MakeMissingMemberError(type, memInfo.Name), typeof(object))
                        );
                        break;
                    default:
                        throw new InvalidOperationException();
                }
            } else {
                memInfo.Body.FinishCondition(error);
            }
        }
        /// <summary> if a member-injector is defined-on or registered-for this type call it </summary>
        private bool MakeOperatorDeleteMemberBody(SetOrDeleteMemberInfo delInfo, DynamicMetaObject instance, Type type, string name) {
            MethodInfo delMem = GetMethod(type, name);

            if (delMem != null) {
                DynamicMetaObject call = MakeCallExpression(delInfo.ResolutionFactory, delMem, instance, new DynamicMetaObject(AstUtils.Constant(delInfo.Name), BindingRestrictions.Empty, delInfo.Name));

                if (delMem.ReturnType == typeof(bool)) {
                    delInfo.Body.AddCondition(
                        call.Expression,
                        AstUtils.Constant(null)
                    );
                } else {
                    delInfo.Body.FinishCondition(call);
                }

                return delMem.ReturnType != typeof(bool);
            }
            return false;
        }
        private void MakeGenericBody(SetOrDeleteMemberInfo memInfo, DynamicMetaObject instance, DynamicMetaObject target, Type type, MemberTracker tracker, DynamicMetaObject errorSuggestion) {
            if (instance != null) {
                tracker = tracker.BindToInstance(instance);
            }

            DynamicMetaObject val = tracker.SetValue(memInfo.ResolutionFactory, this, type, target, errorSuggestion);

            if (val != null) {
                memInfo.Body.FinishCondition(val);
            } else {
                memInfo.Body.FinishCondition(
                    MakeError(tracker.GetError(this), typeof(object))
                );
            }
        }
        /// <summary> if a member-injector is defined-on or registered-for this type call it </summary>
        private bool MakeOperatorDeleteMemberBody(SetOrDeleteMemberInfo delInfo, Expression instance, Type type, string name) {
            MethodInfo delMem = GetMethod(type, name);

            if (delMem != null && delMem.IsSpecialName) {
                Expression call = MakeCallExpression(delInfo.CodeContext, delMem, instance, Ast.Constant(delInfo.Name));

                if (delMem.ReturnType == typeof(bool)) {
                    delInfo.Body.AddCondition(
                        call,
                        Ast.Constant(null)
                    );
                } else {
                    delInfo.Body.FinishCondition(call);
                }

                return delMem.ReturnType != typeof(bool);
            }
            return false;
        }
        private void MakeSetMemberRule(SetOrDeleteMemberInfo memInfo, Type type, Expression self, MetaObject target)
        {
            if (MakeOperatorSetMemberBody(memInfo, self, target, type, "SetMember"))
            {
                return;
            }

            // needed for GetMember call until DynamicAction goes away
            OldDynamicAction act = OldSetMemberAction.Make(
                this,
                memInfo.Name
                );

            MemberGroup members = GetMember(act, type, memInfo.Name);

            // if lookup failed try the strong-box type if available.
            if (members.Count == 0 && typeof(IStrongBox).IsAssignableFrom(type))
            {
                self = Ast.Field(AstUtils.Convert(self, type), type.GetField("Value"));
                type = type.GetGenericArguments()[0];

                members = GetMember(act, type, memInfo.Name);
            }

            Expression   error;
            TrackerTypes memberTypes = GetMemberType(members, out error);

            if (error == null)
            {
                switch (memberTypes)
                {
                case TrackerTypes.Method:
                case TrackerTypes.TypeGroup:
                case TrackerTypes.Type:
                case TrackerTypes.Constructor:
                    memInfo.Body.FinishCondition(
                        MakeError(MakeReadOnlyMemberError(type, memInfo.Name))
                        );
                    break;

                case TrackerTypes.Event:
                    memInfo.Body.FinishCondition(
                        MakeError(MakeEventValidation(members, self, target.Expression, memInfo.CodeContext))
                        );
                    break;

                case TrackerTypes.Field:
                    MakeFieldRule(memInfo, self, target, type, members);
                    break;

                case TrackerTypes.Property:
                    MakePropertyRule(memInfo, self, target, type, members);
                    break;

                case TrackerTypes.Custom:
                    MakeGenericBody(memInfo, self, target, type, members[0]);
                    break;

                case TrackerTypes.All:
                    // no match
                    if (MakeOperatorSetMemberBody(memInfo, self, target, type, "SetMemberAfter"))
                    {
                        return;
                    }

                    memInfo.Body.FinishCondition(
                        MakeError(MakeMissingMemberError(type, memInfo.Name))
                        );
                    break;

                default:
                    throw new InvalidOperationException();
                }
            }
            else
            {
                memInfo.Body.FinishCondition(error);
            }
        }
 private void MakePropertyDeleteStatement(SetOrDeleteMemberInfo delInfo, Expression instance, MethodInfo delete) {
     delInfo.Body.FinishCondition(
         MakeCallExpression(delInfo.CodeContext, delete, instance)
     );
 }
Example #16
0
        private void MakeSetMemberRule(SetOrDeleteMemberInfo memInfo, Type type, DynamicMetaObject self, DynamicMetaObject value, DynamicMetaObject errorSuggestion)
        {
            if (MakeOperatorSetMemberBody(memInfo, self, value, type, "SetMember"))
            {
                return;
            }


            MemberGroup members = GetMember(MemberRequestKind.Set, type, memInfo.Name);

            // if lookup failed try the strong-box type if available.
            if (self != null && members.Count == 0 && typeof(IStrongBox).IsAssignableFrom(type))
            {
                self = new DynamicMetaObject(Ast.Field(AstUtils.Convert(self.Expression, type), type.GetInheritedFields("Value").First()), BindingRestrictions.Empty, ((IStrongBox)self.Value).Value);
                type = type.GetGenericArguments()[0];

                members = GetMember(MemberRequestKind.Set, type, memInfo.Name);
            }

            Expression   error;
            TrackerTypes memberTypes = GetMemberType(members, out error);

            if (error == null)
            {
                switch (memberTypes)
                {
                case TrackerTypes.Method:
                case TrackerTypes.TypeGroup:
                case TrackerTypes.Type:
                case TrackerTypes.Constructor:
                    memInfo.Body.FinishError(
                        errorSuggestion ?? MakeError(MakeReadOnlyMemberError(type, memInfo.Name), BindingRestrictions.Empty, typeof(object))
                        );
                    break;

                case TrackerTypes.Event:
                    memInfo.Body.FinishError(
                        errorSuggestion ?? MakeError(MakeEventValidation(members, self, value, memInfo.ResolutionFactory), BindingRestrictions.Empty, typeof(object))
                        );
                    break;

                case TrackerTypes.Field:
                    MakeFieldRule(memInfo, self, value, type, members, errorSuggestion);
                    break;

                case TrackerTypes.Property:
                    MakePropertyRule(memInfo, self, value, type, members, errorSuggestion);
                    break;

                case TrackerTypes.Custom:
                    MakeGenericBody(memInfo, self, value, type, members[0], errorSuggestion);
                    break;

                case TrackerTypes.All:
                    // no match
                    if (MakeOperatorSetMemberBody(memInfo, self, value, type, "SetMemberAfter"))
                    {
                        return;
                    }

                    memInfo.Body.FinishError(
                        errorSuggestion ?? MakeError(MakeMissingMemberErrorForAssign(type, self, memInfo.Name), BindingRestrictions.Empty, typeof(object))
                        );
                    break;

                default:
                    throw new InvalidOperationException();
                }
            }
            else
            {
                memInfo.Body.FinishError(error);
            }
        }
        /// <summary> if a member-injector is defined-on or registered-for this type call it </summary>
        private bool MakeOperatorSetMemberBody(SetOrDeleteMemberInfo memInfo, DynamicMetaObject self, DynamicMetaObject target, Type type, string name) {
            if (self != null) {
                MethodInfo setMem = GetMethod(type, name);
                if (setMem != null) {
                    ParameterExpression tmp = Ast.Variable(target.Expression.Type, "setValue");
                    memInfo.Body.AddVariable(tmp);

                    var callMo = MakeCallExpression(
                        memInfo.ResolutionFactory, 
                        setMem, 
                        self.Clone(AstUtils.Convert(self.Expression, type)),
                        new DynamicMetaObject(AstUtils.Constant(memInfo.Name), BindingRestrictions.Empty, memInfo.Name),
                        target.Clone(tmp)
                    );

                    var call = Ast.Block(Ast.Assign(tmp, target.Expression), callMo.Expression);

                    if (setMem.ReturnType == typeof(bool)) {
                        memInfo.Body.AddCondition(
                            call,
                            tmp
                        );
                    } else {
                        memInfo.Body.FinishCondition(Ast.Block(call, AstUtils.Convert(tmp, typeof(object))));
                    }

                    return setMem.ReturnType != typeof(bool);
                }
            }

            return false;
        }
 private static Expression MakeGenericPropertyExpression(SetOrDeleteMemberInfo memInfo) {
     return Ast.New(
         typeof(MemberAccessException).GetConstructor(new Type[] { typeof(string) }),
         AstUtils.Constant(memInfo.Name)
     );
 }
Example #19
0
        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)
                        )
                    );
            }
        }
Example #20
0
 private void MakePropertyDeleteStatement(SetOrDeleteMemberInfo delInfo, Expression instance, MethodInfo delete)
 {
     delInfo.Body.FinishCondition(
         MakeCallExpression(delInfo.CodeContext, delete, instance)
         );
 }
Example #21
0
        private void MakeFieldRule(SetOrDeleteMemberInfo memInfo, DynamicMetaObject instance, DynamicMetaObject target, Type targetType, MemberGroup fields, DynamicMetaObject errorSuggestion)
        {
            FieldTracker field = (FieldTracker)fields[0];

            // TODO: Tmp variable for target
            if (instance != null && field.DeclaringType.IsGenericType() && field.DeclaringType.GetGenericTypeDefinition() == typeof(StrongBox <>))
            {
                // work around a CLR bug where we can't access generic fields from dynamic methods.
                Type[] generic = field.DeclaringType.GetGenericArguments();
                memInfo.Body.FinishCondition(
                    MakeReturnValue(
                        Ast.Assign(
                            Ast.Field(
                                AstUtils.Convert(instance.Expression, field.DeclaringType),
                                field.DeclaringType.GetDeclaredField("Value")
                                ),
                            AstUtils.Convert(target.Expression, generic[0])
                            ),
                        target
                        )
                    );
            }
            else if (field.IsInitOnly || field.IsLiteral)
            {
                memInfo.Body.FinishError(
                    errorSuggestion ?? MakeError(
                        MakeReadOnlyMemberError(targetType, memInfo.Name),
                        typeof(object)
                        )
                    );
            }
            else if (field.IsStatic && targetType != field.DeclaringType)
            {
                memInfo.Body.FinishError(
                    errorSuggestion ?? MakeError(
                        MakeStaticAssignFromDerivedTypeError(targetType, instance, field, target, memInfo.ResolutionFactory),
                        typeof(object)
                        )
                    );
            }
            else if (field.DeclaringType.IsValueType() && !field.IsStatic)
            {
                memInfo.Body.FinishError(
                    errorSuggestion ?? MakeError(
                        MakeSetValueTypeFieldError(field, instance, target),
                        typeof(object)
                        )
                    );
            }
            else if (field.IsPublic && field.DeclaringType.IsVisible())
            {
                if (!field.IsStatic && instance == null)
                {
                    memInfo.Body.FinishError(
                        Ast.Throw(
                            Ast.New(
                                typeof(ArgumentException).GetConstructor(new[] { typeof(string) }),
                                AstUtils.Constant("assignment to instance field w/o instance")
                                ),
                            typeof(object)
                            )
                        );
                }
                else
                {
                    memInfo.Body.FinishCondition(
                        MakeReturnValue(
                            Ast.Assign(
                                Ast.Field(
                                    field.IsStatic ?
                                    null :
                                    AstUtils.Convert(instance.Expression, field.DeclaringType),
                                    field.Field
                                    ),
                                ConvertExpression(target.Expression, field.FieldType, ConversionResultKind.ExplicitCast, memInfo.ResolutionFactory)
                                ),
                            target
                            )
                        );
                }
            }
            else
            {
                Debug.Assert(field.IsStatic || instance != null);

                memInfo.Body.FinishCondition(
                    MakeReturnValue(
                        Ast.Call(
                            AstUtils.Convert(AstUtils.Constant(field.Field), typeof(FieldInfo)),
                            typeof(FieldInfo).GetMethod("SetValue", new Type[] { typeof(object), typeof(object) }),
                            field.IsStatic ?
                            AstUtils.Constant(null) :
                            (Expression)AstUtils.Convert(instance.Expression, typeof(object)),
                            AstUtils.Convert(target.Expression, typeof(object))
                            ),
                        target
                        )
                    );
            }
        }