Exemple #1
0
        private MetaObject MakeMetaMethodCall(CallSignature signature, ParameterBinder parameterBinder, TargetInfo targetInfo)
        {
            Restrictions restrictions = Restrictions.Combine(targetInfo.Arguments).Merge(targetInfo.Restrictions);

            if (targetInfo.Instance != null)
            {
                restrictions = targetInfo.Instance.Restrictions.Merge(restrictions);
            }

            if (targetInfo.Instance != null)
            {
                return(CallInstanceMethod(
                           parameterBinder,
                           targetInfo.Targets,
                           targetInfo.Instance,
                           targetInfo.Arguments,
                           signature,
                           restrictions
                           ));
            }

            return(CallMethod(
                       parameterBinder,
                       targetInfo.Targets,
                       targetInfo.Arguments,
                       signature,
                       restrictions));
        }
Exemple #2
0
        private MetaObject MakeMethodIndexRule(string oper, MetaObject[] args)
        {
            MethodInfo[] defaults = GetMethodsFromDefaults(args[0].LimitType.GetDefaultMembers(), oper);
            if (defaults.Length != 0)
            {
                MethodBinder binder = MethodBinder.MakeBinder(
                    this,
                    oper == StandardOperators.GetItem ? "get_Item" : "set_Item",
                    defaults);

                MetaObject[]        selfWithArgs = args;
                ParameterExpression arg2         = null;

                if (oper == StandardOperators.SetItem)
                {
                    Debug.Assert(args.Length >= 2);

                    // need to save arg2 in a temp because it's also our result
                    arg2 = Ast.Variable(args[2].Expression.Type, "arg2Temp");

                    args[2] = new MetaObject(
                        Ast.Assign(arg2, args[2].Expression),
                        args[2].Restrictions
                        );
                }

                BindingTarget target = binder.MakeBindingTarget(CallTypes.ImplicitInstance, selfWithArgs);

                Restrictions restrictions = Restrictions.Combine(args);

                if (target.Success)
                {
                    if (oper == StandardOperators.GetItem)
                    {
                        return(new MetaObject(
                                   target.MakeExpression(),
                                   restrictions.Merge(Restrictions.Combine(target.RestrictedArguments))
                                   ));
                    }
                    else
                    {
                        return(new MetaObject(
                                   Ast.Block(
                                       new ParameterExpression[] { arg2 },
                                       target.MakeExpression(),
                                       arg2
                                       ),
                                   restrictions.Merge(Restrictions.Combine(target.RestrictedArguments))
                                   ));
                    }
                }

                return(MakeError(
                           MakeInvalidParametersError(target),
                           restrictions
                           ));
            }

            return(null);
        }
Exemple #3
0
        private MetaObject IndexOperation(MetaObject fallback, MetaObject[] args, string method)
        {
            ParameterExpression callable = Expression.Variable(typeof(DispCallable), "callable");

            Expression[] callArgs = new Expression[args.Length + 1];
            for (int i = 0; i < args.Length; i++)
            {
                callArgs[i + 1] = args[i].Expression;
            }
            callArgs[0] = callable;

            Expression result = Expression.Block(
                new ParameterExpression[] { callable },
                Expression.Condition(
                    Expression.Call(
                        Expression.Convert(Expression, typeof(IDispatchComObject)),
                        typeof(IDispatchComObject).GetMethod(method),
                        callable
                        ),
                    Expression.Dynamic(new ComInvokeAction(), typeof(object), callArgs),
                    Helpers.Convert(fallback.Expression, typeof(object))
                    )
                );

            return(new MetaObject(
                       result,
                       Restrictions.Combine(args).Merge(IDispatchRestriction()).Merge(fallback.Restrictions)
                       ));
        }
        internal static MetaObject RewriteStrongBoxAsRef(CallSiteBinder action, MetaObject target, MetaObject[] args)
        {
            Debug.Assert(action != null && target != null && args != null);

            var restrictions = target.Restrictions.Merge(Restrictions.Combine(args));

            Expression[] argExpressions = new Expression[args.Length + 1];
            Type[]       signatureTypes = new Type[args.Length + 3]; // args + CallSite, target, returnType

            signatureTypes[0] = typeof(CallSite);

            //TODO: we are not restricting on target type here, but in theory we could.
            //It is a tradeoff between rule reuse and higher polymorphism of the site.
            argExpressions[0] = target.Expression;
            signatureTypes[1] = target.Expression.Type;

            for (int i = 0; i < args.Length; i++)
            {
                MetaObject currArgument = args[i];
                if (IsStrongBoxArg(currArgument))
                {
                    restrictions = restrictions.Merge(Restrictions.GetTypeRestriction(currArgument.Expression, currArgument.LimitType));

                    // we have restricted this argument to LimitType so we can convert and conversion will be trivial cast.
                    Expression boxedValueAccessor = Expression.Field(
                        Helpers.Convert(
                            currArgument.Expression,
                            currArgument.LimitType
                            ),
                        currArgument.LimitType.GetField("Value")
                        );

                    argExpressions[i + 1] = boxedValueAccessor;
                    signatureTypes[i + 2] = boxedValueAccessor.Type.MakeByRefType();
                }
                else
                {
                    argExpressions[i + 1] = currArgument.Expression;
                    signatureTypes[i + 2] = currArgument.Expression.Type;
                }
            }

            // Last signatureType is the return value
            signatureTypes[signatureTypes.Length - 1] = typeof(object);

            return(new MetaObject(
                       Expression.MakeDynamic(
                           Expression.GetDelegateType(signatureTypes),
                           action,
                           argExpressions
                           ),
                       restrictions
                       ));
        }
 public override MetaObject BindCreateInstance(CreateInstanceBinder binder, MetaObject[] args)
 {
     return(new MetaObject(
                Expression.Call(
                    AstUtils.Convert(Expression, typeof(ComTypeClassDesc)),
                    typeof(ComTypeClassDesc).GetMethod("CreateInstance")
                    ),
                Restrictions.Combine(args).Merge(
                    Restrictions.GetTypeRestriction(Expression, typeof(ComTypeClassDesc))
                    )
                ));
 }
Exemple #6
0
 private static MetaObject MakeOperatorError(OperatorInfo info, MetaObject[] args)
 {
     return(new MetaObject(
                Ast.Throw(
                    AstUtils.ComplexCallHelper(
                        typeof(BinderOps).GetMethod("BadArgumentsForOperation"),
                        ArrayUtils.Insert((Expression)Ast.Constant(info.Operator), MetaObject.GetExpressions(args))
                        )
                    ),
                Restrictions.Combine(args)
                ));
 }
Exemple #7
0
        private static MetaObject MakeInvalidParametersRule(CallTypes callType, CallSignature signature, DefaultBinder binder, IList <MetaObject> args, Restrictions restrictions, BindingTarget bt)
        {
            Restrictions restriction = MakeSplatTests(callType, signature, true, args);

            // restrict to the exact type of all parameters for errors
            for (int i = 0; i < args.Count; i++)
            {
                args[i] = args[i].Restrict(args[i].LimitType);
            }

            return(MakeError(
                       binder.MakeInvalidParametersError(bt),
                       restrictions.Merge(Restrictions.Combine(args).Merge(restriction))
                       ));
        }
Exemple #8
0
        private MetaObject TryMakeBindingTarget(MethodInfo[] targets, MetaObject[] args, Expression codeContext, Restrictions restrictions)
        {
            MethodBinder mb = MethodBinder.MakeBinder(this, targets[0].Name, targets);

            BindingTarget target = mb.MakeBindingTarget(CallTypes.None, args);

            if (target.Success)
            {
                return(new MetaObject(
                           target.MakeExpression(new ParameterBinderWithCodeContext(this, codeContext)),
                           restrictions.Merge(Restrictions.Combine(target.RestrictedArguments))
                           ));
            }

            return(null);
        }
Exemple #9
0
        private MetaObject TryMakeInvertedBindingTarget(MethodBase[] targets, MetaObject[] args)
        {
            MethodBinder mb = MethodBinder.MakeBinder(this, targets[0].Name, targets);

            MetaObject[]  selfArgs = args;
            BindingTarget target   = mb.MakeBindingTarget(CallTypes.None, selfArgs);

            if (target.Success)
            {
                return(new MetaObject(
                           Ast.Not(target.MakeExpression()),
                           Restrictions.Combine(target.RestrictedArguments)
                           ));
            }

            return(null);
        }
Exemple #10
0
        private MetaObject TryNumericComparison(OperatorInfo info, MetaObject[] args)
        {
            MethodInfo[] targets = FilterNonMethods(
                args[0].LimitType,
                GetMember(OldDoOperationAction.Make(this, info.Operator),
                          args[0].LimitType,
                          "Compare")
                );

            if (targets.Length > 0)
            {
                MethodBinder  mb     = MethodBinder.MakeBinder(this, targets[0].Name, targets);
                BindingTarget target = mb.MakeBindingTarget(CallTypes.None, args);
                if (target.Success)
                {
                    Expression call = AstUtils.Convert(target.MakeExpression(), typeof(int));
                    switch (info.Operator)
                    {
                    case Operators.GreaterThan: call = Ast.GreaterThan(call, Ast.Constant(0)); break;

                    case Operators.LessThan: call = Ast.LessThan(call, Ast.Constant(0)); break;

                    case Operators.GreaterThanOrEqual: call = Ast.GreaterThanOrEqual(call, Ast.Constant(0)); break;

                    case Operators.LessThanOrEqual: call = Ast.LessThanOrEqual(call, Ast.Constant(0)); break;

                    case Operators.Equals: call = Ast.Equal(call, Ast.Constant(0)); break;

                    case Operators.NotEquals: call = Ast.NotEqual(call, Ast.Constant(0)); break;

                    case Operators.Compare:
                        break;
                    }

                    return(new MetaObject(
                               call,
                               Restrictions.Combine(target.RestrictedArguments)
                               ));
                }
            }

            return(null);
        }
        internal MetaObject Invoke()
        {
            _keywordArgNames = GetArgumentNames();
            // will not include implicit instance argument (if any)
            Type[] explicitArgTypes = _args.Map(a => a.LimitType);
            Type[] marshalArgTypes  = _args.Map(a => MarshalType(a));

            Expression[] explicitArgExprs = _args.Map(a => a.Expression);
            _totalExplicitArgs = explicitArgTypes.Length;

            _varEnumSelector = new VarEnumSelector(marshalArgTypes);

            // We already tested the instance, so no need to test it again
            for (int i = 0; i < explicitArgTypes.Length; i++)
            {
                _restrictions = _restrictions.Merge(Restrictions.GetTypeRestriction(explicitArgExprs[i], explicitArgTypes[i]));
            }

            return(new MetaObject(
                       CreateScope(MakeIDispatchInvokeTarget()),
                       Restrictions.Combine(_args).Merge(_restrictions)
                       ));
        }
Exemple #12
0
            // TODO: support for IgnoreCase in underlying ScriptScope APIs
            public override MetaObject BindInvokeMember(InvokeMemberBinder action, MetaObject[] args)
            {
                var fallback = action.FallbackInvokeMember(this, args);
                var result   = Expression.Variable(typeof(object), "result");

                var fallbackInvoke = action.FallbackInvoke(new MetaObject(result, Restrictions.Empty), args, null);

                return(new MetaObject(
                           Expression.Block(
                               new ParameterExpression[] { result },
                               Expression.Condition(
                                   Expression.Call(
                                       AstUtils.Convert(Expression, typeof(ScriptScope)),
                                       typeof(ScriptScope).GetMethod("TryGetVariable", new[] { typeof(string), typeof(object).MakeByRefType() }),
                                       Expression.Constant(action.Name),
                                       result
                                       ),
                                   Expression.Convert(fallbackInvoke.Expression, typeof(object)),
                                   Expression.Convert(fallback.Expression, typeof(object))
                                   )
                               ),
                           Restrictions.Combine(args).Merge(Restrictions.GetTypeRestriction(Expression, typeof(ScriptScope))).Merge(fallback.Restrictions)
                           ));
            }
Exemple #13
0
        private MetaObject CallWorker(ParameterBinder parameterBinder, IList <MethodBase> targets, IList <MetaObject> args, CallSignature signature, CallTypes callType, Restrictions restrictions, NarrowingLevel minLevel, NarrowingLevel maxLevel, string name, out BindingTarget target)
        {
            ContractUtils.RequiresNotNull(parameterBinder, "parameterBinder");
            ContractUtils.RequiresNotNullItems(args, "args");
            ContractUtils.RequiresNotNullItems(targets, "targets");
            ContractUtils.RequiresNotNull(restrictions, "restrictions");

            MetaObject[] finalArgs;
            SymbolId[]   argNames;

            if (callType == CallTypes.ImplicitInstance)
            {
                GetArgumentNamesAndTypes(signature, ArrayUtils.RemoveFirst(args), out argNames, out finalArgs);
                finalArgs = ArrayUtils.Insert(args[0], finalArgs);
            }
            else
            {
                GetArgumentNamesAndTypes(signature, args, out argNames, out finalArgs);
            }

            // attempt to bind to an individual method
            MethodBinder binder = MethodBinder.MakeBinder(
                this,
                name ?? GetTargetName(targets),
                targets,
                argNames,
                minLevel,
                maxLevel);

            target = binder.MakeBindingTarget(callType, finalArgs);

            if (target.Success)
            {
                // if we succeed make the target for the rule
                return(new MetaObject(
                           target.MakeExpression(parameterBinder),
                           restrictions.Merge(MakeSplatTests(callType, signature, args).Merge(Restrictions.Combine(target.RestrictedArguments)))
                           ));
            }
            // make an error rule
            return(MakeInvalidParametersRule(callType, signature, this, args, restrictions, target));
        }
Exemple #14
0
        /// <summary>
        /// Produces a rule for comparing a value to null - supports comparing object references and nullable types.
        /// </summary>
        private static MetaObject TryNullComparisonRule(MetaObject[] args)
        {
            Type otherType = args[0].LimitType;

            Restrictions restrictions = Restrictions.GetTypeRestriction(args[0].Expression, args[0].LimitType).Merge(Restrictions.Combine(args));

            if (args[0].LimitType == typeof(Null))
            {
                if (!otherType.IsValueType)
                {
                    return(new MetaObject(
                               Ast.Equal(args[0].Expression, Ast.Constant(null)),
                               restrictions
                               ));
                }
                else if (otherType.GetGenericTypeDefinition() == typeof(Nullable <>))
                {
                    return(new MetaObject(
                               Ast.Property(args[0].Expression, otherType.GetProperty("HasValue")),
                               restrictions
                               ));
                }
            }
            else if (otherType == typeof(Null))
            {
                if (!args[0].LimitType.IsValueType)
                {
                    return(new MetaObject(
                               Ast.Equal(args[0].Expression, Ast.Constant(null)),
                               restrictions
                               ));
                }
                else if (args[0].LimitType.GetGenericTypeDefinition() == typeof(Nullable <>))
                {
                    return(new MetaObject(
                               Ast.Property(args[0].Expression, otherType.GetProperty("HasValue")),
                               restrictions
                               ));
                }
            }

            return(null);
        }
Exemple #15
0
        private static MetaObject TryPrimitiveCompare(OperatorInfo info, MetaObject[] args)
        {
            if (TypeUtils.GetNonNullableType(args[0].LimitType) == TypeUtils.GetNonNullableType(args[1].LimitType) &&
                TypeUtils.IsNumeric(args[0].LimitType))
            {
                Expression arg0 = args[0].Expression;
                Expression arg1 = args[1].Expression;

                // TODO: Nullable<PrimitveType> Support
                Expression expr;
                switch (info.Operator)
                {
                case Operators.Equals: expr = Ast.Equal(arg0, arg1); break;

                case Operators.NotEquals: expr = Ast.NotEqual(arg0, arg1); break;

                case Operators.GreaterThan: expr = Ast.GreaterThan(arg0, arg1); break;

                case Operators.LessThan: expr = Ast.LessThan(arg0, arg1); break;

                case Operators.GreaterThanOrEqual: expr = Ast.GreaterThanOrEqual(arg0, arg1); break;

                case Operators.LessThanOrEqual: expr = Ast.LessThanOrEqual(arg0, arg1); break;

                default: throw new InvalidOperationException();
                }

                return(new MetaObject(
                           expr,
                           Restrictions.GetTypeRestriction(arg0, args[0].LimitType).Merge(Restrictions.GetTypeRestriction(arg1, args[0].LimitType)).Merge(Restrictions.Combine(args))
                           ));
            }

            return(null);
        }
 private Restrictions ComTypeLibInfoRestrictions(params MetaObject[] args)
 {
     return(Restrictions.Combine(args).Merge(Restrictions.GetTypeRestriction(Expression, typeof(ComTypeLibInfo))));
 }
Exemple #17
0
        private static MetaObject TryMakeDefaultUnaryRule(OperatorInfo info, Expression codeContext, MetaObject[] args)
        {
            if (args.Length == 1)
            {
                Restrictions restrictions = Restrictions.GetTypeRestriction(args[0].Expression, args[0].LimitType).Merge(Restrictions.Combine(args));
                switch (info.Operator)
                {
                case Operators.IsTrue:
                    if (args[0].LimitType == typeof(bool))
                    {
                        return(args[0]);
                    }
                    break;

                case Operators.Negate:
                    if (TypeUtils.IsArithmetic(args[0].LimitType))
                    {
                        return(new MetaObject(
                                   Ast.Negate(args[0].Expression),
                                   restrictions
                                   ));
                    }
                    break;

                case Operators.Not:
                    if (TypeUtils.IsIntegerOrBool(args[0].LimitType))
                    {
                        return(new MetaObject(
                                   Ast.Not(args[0].Expression),
                                   restrictions
                                   ));
                    }
                    break;

                case Operators.Documentation:
                    object[] attrs         = args[0].LimitType.GetCustomAttributes(typeof(DocumentationAttribute), true);
                    string   documentation = String.Empty;

                    if (attrs.Length > 0)
                    {
                        documentation = ((DocumentationAttribute)attrs[0]).Documentation;
                    }

                    return(new MetaObject(
                               Ast.Constant(documentation),
                               restrictions
                               ));

                case Operators.MemberNames:
                    if (typeof(IMembersList).IsAssignableFrom(args[0].LimitType))
                    {
                        return(MakeIMembersListRule(codeContext, args[0]));
                    }

                    MemberInfo[] members             = args[0].LimitType.GetMembers();
                    Dictionary <string, string> mems = new Dictionary <string, string>();
                    foreach (MemberInfo mi in members)
                    {
                        mems[mi.Name] = mi.Name;
                    }

                    string[] res = new string[mems.Count];
                    mems.Keys.CopyTo(res, 0);

                    return(new MetaObject(
                               Ast.Constant(res),
                               restrictions
                               ));

                case Operators.CallSignatures:
                    return(MakeCallSignatureResult(CompilerHelpers.GetMethodTargets(args[0].LimitType), args[0]));

                case Operators.IsCallable:
                    // IsCallable() is tightly tied to Call actions. So in general, we need the call-action providers to also
                    // provide IsCallable() status.
                    // This is just a rough fallback. We could also attempt to simulate the default CallBinder logic to see
                    // if there are any applicable calls targets, but that would be complex (the callbinder wants the argument list,
                    // which we don't have here), and still not correct.
                    bool callable = false;
                    if (typeof(Delegate).IsAssignableFrom(args[0].LimitType) ||
                        typeof(MethodGroup).IsAssignableFrom(args[0].LimitType))
                    {
                        callable = true;
                    }

                    return(new MetaObject(
                               Ast.Constant(callable),
                               restrictions
                               ));
                }
            }
            return(null);
        }
Exemple #18
0
        private MetaObject MakeArrayIndexRule(string oper, MetaObject[] args)
        {
            if (CanConvertFrom(GetArgType(args, 1), typeof(int), false, NarrowingLevel.All))
            {
                Restrictions restrictions = Restrictions.GetTypeRestriction(args[0].Expression, args[0].LimitType).Merge(Restrictions.Combine(args));

                if (oper == StandardOperators.GetItem)
                {
                    return(new MetaObject(
                               Ast.ArrayAccess(
                                   args[0].Expression,
                                   ConvertIfNeeded(args[1].Expression, typeof(int))
                                   ),
                               restrictions
                               ));
                }
                else
                {
                    return(new MetaObject(
                               Ast.Assign(
                                   Ast.ArrayAccess(
                                       args[0].Expression,
                                       ConvertIfNeeded(args[1].Expression, typeof(int))
                                       ),
                                   ConvertIfNeeded(args[2].Expression, args[0].LimitType.GetElementType())
                                   ),
                               restrictions.Merge(args[1].Restrictions)
                               ));
                }
            }

            return(null);
        }