예제 #1
0
        public override DynamicMetaObject FallbackInvoke(
            DynamicMetaObject target, DynamicMetaObject[] args,
            DynamicMetaObject errorSuggestion)
        {
            var deferArgs = Runtime.CheckDeferArgs(target, args);

            if (deferArgs != null)
            {
                return(Defer(deferArgs));
            }

            if (target.Value == null)
            {
                return(Runtime.CheckTargetNullReference(target, "Not invokable: " + Runtime.CollectParameterInfo(target, args)));
            }

            if (Runtime.Prototypep(target.Value))
            {
                var indexingExpr = Runtime.GetIndexingExpression(target, args);
                var restrictions = Runtime.GetTargetArgsRestrictions(target, args, false);

                if (indexingExpr == null)
                {
                    return(errorSuggestion ??
                           Runtime.CreateThrow(
                               target, args, restrictions,
                               typeof(InvalidOperationException),
                               "Not invokable: " + Runtime.CollectParameterInfo(target, args)));
                }

                return(new DynamicMetaObject(Runtime.EnsureObjectResult(indexingExpr), restrictions));
            }

            if (target.LimitType.IsSubclassOf(typeof(Delegate)))
            {
                var parms = target.LimitType.GetMethod("Invoke").GetParameters();

                if (parms.Length == args.Length)
                {
                    // Don't need to check if argument types match parameters.
                    // If they don't, users get an argument conversion error.
                    var callArgs   = Runtime.ConvertArguments(args, parms);
                    var expression = Expression.Invoke(
                        Expression.Convert(target.Expression, target.LimitType),
                        callArgs);
                    return(new DynamicMetaObject(
                               Runtime.EnsureObjectResult(expression),
                               BindingRestrictions.GetTypeRestriction(target.Expression,
                                                                      target.LimitType)));
                }
            }

            return(errorSuggestion ??
                   Runtime.CreateThrow(
                       target, args,
                       BindingRestrictions.GetTypeRestriction(target.Expression,
                                                              target.LimitType),
                       typeof(InvalidOperationException),
                       "Not invokable: " + Runtime.CollectParameterInfo(target, args)));
        }
예제 #2
0
        public override DynamicMetaObject FallbackSetIndex(
            DynamicMetaObject target, DynamicMetaObject[] indexes,
            DynamicMetaObject value, DynamicMetaObject errorSuggestion)
        {
            var deferArgs = Runtime.CheckDeferArgs(target, indexes);

            if (deferArgs != null)
            {
                return(Defer(deferArgs));
            }

            if (target.Value == null)
            {
                return(Runtime.CheckTargetNullReference(target, "Cannot set index on null reference: "
                                                        + target.LimitType.FullName + Runtime.CollectParameterInfo(target, indexes)));
            }

            Expression valueExpr = value.Expression;

            Debug.Assert(target.HasValue && target.LimitType != typeof(Array));
            Type valueType;
            var  indexingExpr = Runtime.GetIndexingExpression(target, indexes, out valueType);

            if (indexingExpr == null)
            {
                return(errorSuggestion ??
                       Runtime.CreateThrow(
                           target, indexes, BindingRestrictions.Empty,
                           typeof(InvalidOperationException),
                           "No set indexer found: " + target.LimitType.FullName + Runtime.CollectParameterInfo(target, indexes)));
            }

            var setIndexExpr = Expression.Assign(indexingExpr, Expression.Convert(valueExpr, valueType));

            BindingRestrictions restrictions = Runtime.GetTargetArgsRestrictions(target, indexes, false);

            return(new DynamicMetaObject(Runtime.EnsureObjectResult(setIndexExpr), restrictions));
        }
예제 #3
0
        public override DynamicMetaObject FallbackGetIndex(
            DynamicMetaObject target, DynamicMetaObject[] indexes,
            DynamicMetaObject errorSuggestion)
        {
            var deferArgs = Runtime.CheckDeferArgs(target, indexes);

            if (deferArgs != null)
            {
                return(Defer(deferArgs));
            }

            if (target.Value == null)
            {
                var expr          = Expression.Constant(null);
                var restrictions2 = BindingRestrictions.GetInstanceRestriction(target.Expression, null);
                return(new DynamicMetaObject(expr, restrictions2));
            }

            // Find our own binding.
            //
            // Conversions created in GetIndexExpression must be consistent with
            // restrictions made in GetTargetArgsRestrictions.
            var indexingExpr = Runtime.GetIndexingExpression(target, indexes);

            if (indexingExpr == null)
            {
                return(errorSuggestion ??
                       Runtime.CreateThrow(
                           target, indexes, BindingRestrictions.Empty,
                           typeof(InvalidOperationException),
                           "No get indexer found: " + target.LimitType.FullName + Runtime.CollectParameterInfo(target, indexes)));
            }

            var restrictions = Runtime.GetTargetArgsRestrictions(target, indexes, false);

            return(new DynamicMetaObject(Runtime.EnsureObjectResult(indexingExpr), restrictions));
        }
예제 #4
0
        public override DynamicMetaObject FallbackSetMember(
            DynamicMetaObject target, DynamicMetaObject value,
            DynamicMetaObject errorSuggestion)
        {
            // Used by (set-attr obj name value)

            if (!target.HasValue)
            {
                return(Defer(target));
            }

            var name = Name.LispToPascalCaseName();

            if (target.Value == null)
            {
                var id = target.LimitType.Name + "." + name;
                return(Runtime.CheckTargetNullReference(target, "Cannot set property on null reference:" + id + "(null)"));
            }

            var flags   = BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy;
            var members = target.LimitType.GetMember(name, flags);

            if (members.Length == 1 && members[0] is PropertyInfo)
            {
                var prop = (PropertyInfo)members[0];
                var val  = Expression.Convert(value.Expression, prop.PropertyType);
                var expr = Expression.Assign(Expression.MakeMemberAccess(Expression.Convert(target.Expression, prop.DeclaringType), prop), val);
                return(new DynamicMetaObject(Runtime.EnsureObjectResult(expr),
                                             BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType)));
            }
            else if (members.Length == 1 && members[0] is FieldInfo)
            {
                var field = (FieldInfo)members[0];
                var val   = Expression.Convert(value.Expression, field.FieldType);
                var expr  = Expression.Assign(Expression.MakeMemberAccess(Expression.Convert(target.Expression, field.DeclaringType), field), val);
                return(new DynamicMetaObject(Runtime.EnsureObjectResult(expr),
                                             BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType)));
            }
            else if (members.Length == 1 && members[0] is EventInfo)
            {
                //public static void AddEventHandler( System.Reflection.EventInfo eventinfo, object target, object func )

                var evt  = (EventInfo)members[0];
                var expr = Expression.Call(Runtime.AddEventHandlerMethod,
                                           Expression.Constant(evt, typeof(EventInfo)),
                                           Expression.Convert(target.Expression, evt.DeclaringType),
                                           Expression.Convert(value.Expression, typeof(IApply)));
                return(new DynamicMetaObject(Runtime.EnsureObjectResult(expr),
                                             BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType)));
            }
            else
            {
                return(errorSuggestion ??
                       Runtime.CreateThrow(
                           target, null,
                           BindingRestrictions.GetTypeRestriction(target.Expression,
                                                                  target.LimitType),
                           typeof(MissingMemberException),
                           "Property or field not found: " + target.LimitType.Name + "." + name + Runtime.CollectParameterInfo(target)));
            }
        }
예제 #5
0
        public override DynamicMetaObject FallbackInvokeMember(
            DynamicMetaObject target, DynamicMetaObject[] args,
            DynamicMetaObject errorSuggestion)
        {
            var deferArgs = Runtime.CheckDeferArgs(target, args);

            if (deferArgs != null)
            {
                return(Defer(deferArgs));
            }

            var limitType = target.LimitType;
            var name      = Name.LispToPascalCaseName();

            if (target.Value == null)
            {
                return(Runtime.CheckTargetNullReference(target,
                                                        "Cannot invoke a method on a null reference:"
                                                        + limitType.FullName + "." + name + Runtime.CollectParameterInfo(target, args)));
            }

            var builtin = Runtime.FindImportedFunction(limitType, Name);

            if (builtin != null)
            {
                DynamicMetaObject result;
                if (builtin.TryBindInvokeBestInstanceMethod(false, target, target, args, out result))
                {
                    return(result);
                }
            }

            var  flags   = BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy;
            var  methods = new List <CandidateMethod <MethodInfo> >();
            bool createdParamArray;

            foreach (var m in limitType.GetMember(name, flags))
            {
                MethodInfo mi;

                if (m is PropertyInfo)
                {
                    mi = ((PropertyInfo)m).GetGetMethod();
                }
                else
                {
                    mi = m as MethodInfo;
                }

                if (mi != null && Runtime.ParametersMatchArguments(mi.GetParameters(), args, out createdParamArray))
                {
                    Runtime.InsertInMostSpecificOrder(methods, mi, createdParamArray);
                }
            }

            if (methods.Count == 0 && (Name.StartsWith("set-") || Name.StartsWith("get-")))
            {
                // Fallback to special handling to change .set-bla to .set_bla if the former has failed.
                name = Name.Left(3) + "_" + Name.Substring(4).LispToPascalCaseName();

                foreach (var m in limitType.GetMember(name, flags))
                {
                    MethodInfo mi;

                    if (m is PropertyInfo)
                    {
                        mi = ((PropertyInfo)m).GetGetMethod();
                    }
                    else
                    {
                        mi = m as MethodInfo;
                    }

                    if (mi != null && Runtime.ParametersMatchArguments(mi.GetParameters(), args, out createdParamArray))
                    {
                        Runtime.InsertInMostSpecificOrder(methods, mi, createdParamArray);
                    }
                }
            }

            var restrictions = Runtime.GetTargetArgsRestrictions(target, args, false);

            if (methods.Count == 0)
            {
                return(errorSuggestion ?? Runtime.CreateThrow(target, args, restrictions, typeof(MissingMemberException),
                                                              "No (suitable) method found: " + limitType.FullName + "." + name + Runtime.CollectParameterInfo(target, args)));
            }
            else
            {
                var        method    = methods[0].Method;
                var        callArgs2 = Runtime.ConvertArguments(args, method.GetParameters());
                Expression expr;

                if (method.IsStatic)
                {
                    // NOT REACHED
                    // static
                    // extension with target as extra parameter
                    expr = Expression.Call(method, callArgs2);
                }
                else
                {
                    expr = Expression.Call(Expression.Convert(target.Expression, limitType), method, callArgs2);
                }

                return(new DynamicMetaObject(Runtime.EnsureObjectResult(expr), restrictions));
            }
        }
예제 #6
0
        public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject errorSuggestion)
        {
            // Used by (attr obj name)

            if (!target.HasValue)
            {
                return(Defer(target));
            }

            var flags   = BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy;
            var name    = Name.LispToPascalCaseName();
            var members = target.LimitType.GetMember(name, flags);

            if (target.Value == null)
            {
                var id = target.LimitType.Name + "." + name;
                return(Runtime.CheckTargetNullReference(target, "Cannot get property on null reference:" + id + "(null)"));
            }

            if (members.Length == 1 && (members[0] is PropertyInfo || members[0] is FieldInfo))
            {
                var expr = Expression.MakeMemberAccess(Expression.Convert(target.Expression, members[0].DeclaringType), members[0]);

                return(new DynamicMetaObject(Runtime.EnsureObjectResult(expr),
                                             // Don't need restriction test for name since this
                                             // rule is only used where binder is used, which is
                                             // only used in sites with this binder.Name.
                                             BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType)));
            }
            else
            {
                return(errorSuggestion ??
                       Runtime.CreateThrow(
                           target, null,
                           BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType),
                           typeof(MissingMemberException),
                           "Property or field not found: " + target.LimitType.Name + "." + name + Runtime.CollectParameterInfo(target)));
            }
        }
예제 #7
0
        public override DynamicMetaObject BindInvoke(InvokeBinder binder, DynamicMetaObject[] args)
        {
            DynamicMetaObject result;

            if (!runtimeModel.TryBindInvokeBestMethod(true, this, args, out result))
            {
                throw new MissingMemberException("No (suitable) method found: " + runtimeModel.FullName + Runtime.CollectParameterInfo(args));
            }
            return(result);
        }
예제 #8
0
        public override DynamicMetaObject BindInvoke(InvokeBinder binder, DynamicMetaObject[] args)
        {
            bool createdParamArray;
            var  ctors = new List <CandidateMethod <ConstructorInfo> >();

            foreach (ConstructorInfo m in runtimeModel.Members)
            {
                if (m.IsStatic)
                {
                    continue;
                }

                if (Runtime.ParametersMatchArguments(m.GetParameters(), args, out createdParamArray))
                {
                    Runtime.InsertInMostSpecificOrder(ctors, m, createdParamArray);
                }
            }

            if (ctors.Count == 0)
            {
                throw new MissingMemberException("No (suitable) constructor found: new " + runtimeModel.FullName + Runtime.CollectParameterInfo(args));
            }

            var ctor         = ctors[0].Method;
            var restrictions = Runtime.GetTargetArgsRestrictions(this, args, true);
            var callArgs     = Runtime.ConvertArguments(args, ctor.GetParameters());

            return(new DynamicMetaObject(Runtime.EnsureObjectResult(Expression.New(ctor, callArgs)), restrictions));
        }