示例#1
0
        // (clr-field-set! type field-name obj value)
        public override Expression Generate(object args, CodeBlock cb)
        {
            Type   t        = null;
            string type     = null;
            bool   inferred = false;

            object rtype = Builtins.First(args);

            ExtractTypeInfo(rtype, out t, out type, out inferred);

            string member = SymbolTable.IdToString((SymbolId)Builtins.Second(Builtins.Second(args)));

            BindingFlags bf = BindingFlags.Instance;

            Expression instance = GetAst(Builtins.Third(args), cb);

            if (instance is ConstantExpression && ((ConstantExpression)instance).Value == null)
            {
                bf       = BindingFlags.Static;
                instance = null;

                if (inferred)
                {
                    ClrSyntaxError("clr-field-set!", "type inference not possible on static member", member);
                }
            }
            else if (inferred)
            {
                if (instance is UnaryExpression && instance.Type == typeof(object))
                {
                    var ue = (UnaryExpression)instance;
                    instance = ue.Operand;
                }
                t = instance.Type;
            }
            else
            {
                instance = ConvertToHelper(t, instance);
            }
            type = t.Name;


            FieldInfo fi = t.GetField(member, BindingFlags.Public | bf | BindingFlags.FlattenHierarchy);

            if (fi == null)
            {
                ClrSyntaxError("clr-field-set!", "field not found on type: " + type, args);
            }

            if (fi.IsLiteral)
            {
                ClrSyntaxError("clr-field-set!", "cannot set a constant field: " + type);
            }

            Expression value = GetAst(Builtins.Car(Builtins.LastPair(args)), cb);

            return(Ast.Comma(Ast.AssignField(instance, fi, value), Ast.ReadField(null, Unspecified)));
        }
        internal override Expression ToExpression(MethodBinderContext context, IList <ArgBuilder> args, IList <Expression> parameters, Expression ret)
        {
            List <Expression> sets = new List <Expression>();

            Variable tmp = null;// context.GetTemporary(ret.Type, "val");

            for (int i = 0; i < _indexesUsed.Length; i++)
            {
                Expression value = parameters[parameters.Count - _kwArgCount + _indexesUsed[i]];
                switch (_membersSet[i].MemberType)
                {
                case MemberTypes.Field:
                    FieldInfo fi = (FieldInfo)_membersSet[i];
                    if (!fi.IsLiteral && !fi.IsInitOnly)
                    {
                        sets.Add(Ast.AssignField(Ast.Read(tmp), fi, Ast.ConvertHelper(value, fi.FieldType)));
                    }
                    else
                    {
                        // call a helper which throws the error but "returns object"
                        sets.Add(
                            Ast.Convert(
                                Ast.Call(
                                    typeof(RuntimeHelpers).GetMethod("ReadOnlyAssignError"),
                                    Ast.Constant(true),
                                    Ast.Constant(fi.Name)
                                    ),
                                fi.FieldType
                                )
                            );
                    }
                    break;

                case MemberTypes.Property:
                    PropertyInfo pi = (PropertyInfo)_membersSet[i];
                    if (pi.GetSetMethod(ScriptDomainManager.Options.PrivateBinding) != null)
                    {
                        sets.Add(Ast.AssignProperty(Ast.Read(tmp), pi, Ast.ConvertHelper(value, pi.PropertyType)));
                    }
                    else
                    {
                        // call a helper which throws the error but "returns object"
                        sets.Add(
                            Ast.Convert(
                                Ast.Call(
                                    typeof(RuntimeHelpers).GetMethod("ReadOnlyAssignError"),
                                    Ast.Constant(false),
                                    Ast.Constant(pi.Name)
                                    ),
                                pi.PropertyType
                                )
                            );
                    }
                    break;
                }
            }

            Expression newCall = Ast.Comma(
                0,
                ArrayUtils.Insert <Expression>(
                    Ast.Assign(tmp, ret),
                    sets.ToArray()
                    )
                );

            return(_builder.ToExpression(context, args, parameters, newCall));
        }
示例#3
0
        private void MakeFieldRule(Type targetType, MemberGroup fields)
        {
            FieldTracker field = (FieldTracker)fields[0];

            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();
                AddToBody(
                    Rule.MakeReturn(Binder,
                                    MakeReturnValue(
                                        Ast.Call(
                                            typeof(BinderOps).GetMethod("UpdateBox").MakeGenericMethod(generic),
                                            Ast.ConvertHelper(Instance, field.DeclaringType),
                                            Ast.ConvertHelper(Rule.Parameters[1], generic[0])
                                            )
                                        )
                                    )
                    );
            }
            else if (field.IsInitOnly || field.IsLiteral || (field.IsStatic && targetType != field.DeclaringType))         // TODO: Field static check too python specific
            {
                AddToBody(Binder.MakeReadOnlyMemberError(Rule, targetType, StringName));
            }
            else if (field.DeclaringType.IsValueType)
            {
                AddToBody(Rule.MakeError(Ast.New(typeof(ArgumentException).GetConstructor(new Type[] { typeof(string) }), Ast.Constant("cannot assign to value types"))));
            }
            else if (field.IsPublic && field.DeclaringType.IsVisible)
            {
                AddToBody(
                    Rule.MakeReturn(
                        Binder,
                        MakeReturnValue(
                            Ast.AssignField(
                                field.IsStatic ?
                                null :
                                Ast.Convert(Rule.Parameters[0], field.DeclaringType),
                                field.Field,
                                Binder.ConvertExpression(Rule.Parameters[1], field.FieldType)
                                )
                            )
                        )
                    );
            }
            else
            {
                AddToBody(
                    Rule.MakeReturn(
                        Binder,
                        MakeReturnValue(
                            Ast.Call(
                                Ast.ConvertHelper(Ast.RuntimeConstant(field.Field), typeof(FieldInfo)),
                                typeof(FieldInfo).GetMethod("SetValue", new Type[] { typeof(object), typeof(object) }),
                                field.IsStatic ?
                                Ast.Null() :
                                (Expression)Ast.ConvertHelper(Instance, typeof(object)),
                                Ast.ConvertHelper(Rule.Parameters[1], typeof(object))
                                )
                            )
                        )
                    );
            }
        }