Inheritance: Microsoft.Scripting.Actions.Calls.OverloadResolver
Ejemplo n.º 1
0
            public override DynamicMetaObject /*!*/ FallbackInvoke(DynamicMetaObject /*!*/ target, DynamicMetaObject /*!*/[] /*!*/ args,
                                                                   DynamicMetaObject errorSuggestion)
            {
                // Used in combination with GetMember to compose InvokeMember operation.
                // Gets here only if the target is not a callable meta-object.

                var metaBuilder = new MetaObjectBuilder(this, target, args);
                var callArgs    = new CallArguments(_context, target, args, CallInfo);

                metaBuilder.AddTypeRestriction(target.GetLimitType(), target.Expression);

                RubyOverloadResolver.NormalizeArguments(metaBuilder, callArgs, 0, 0);
                if (!metaBuilder.Error)
                {
                    // no arguments => just return the target:
                    metaBuilder.Result = target.Expression;
                }
                else
                {
                    // any arguments found (expected none):
                    metaBuilder.SetMetaResult(errorSuggestion, false);
                }

                return(metaBuilder.CreateMetaObject(this));
            }
Ejemplo n.º 2
0
        public override int GetArity()
        {
            int  minParameters = Int32.MaxValue;
            int  maxParameters = 0;
            bool hasOptional   = false;

            foreach (OverloadInfo method in MethodBases)
            {
                int mandatory, optional;
                RubyOverloadResolver.GetParameterCount(method, CallConvention, out mandatory, out optional);
                if (mandatory < minParameters)
                {
                    minParameters = mandatory;
                }
                if (mandatory > maxParameters)
                {
                    maxParameters = mandatory;
                }
                if (!hasOptional && optional > 0)
                {
                    hasOptional = true;
                }
            }
            if (hasOptional || maxParameters > minParameters)
            {
                return(-minParameters - 1);
            }
            else
            {
                return(minParameters);
            }
        }
Ejemplo n.º 3
0
 internal override void BuildCallNoFlow(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args, string /*!*/ name)
 {
     RubyOverloadResolver.NormalizeArguments(metaBuilder, args, 0, 0);
     if (!metaBuilder.Error)
     {
         metaBuilder.Result = Methods.GetInstanceVariable.OpCall(
             AstUtils.Convert(args.MetaScope.Expression, typeof(RubyScope)),
             AstUtils.Box(args.TargetExpression),
             AstUtils.Constant(InstanceVariableName)
             );
     }
 }
Ejemplo n.º 4
0
        private bool IsOverloadSignature(OverloadInfo /*!*/ method, Type /*!*/[] /*!*/ parameterTypes)
        {
            int firstInfo = RubyOverloadResolver.GetHiddenParameterCount(method, CallConvention);
            var infos     = method.Parameters;

            if (infos.Count - firstInfo != parameterTypes.Length)
            {
                return(false);
            }

            for (int i = 0; i < parameterTypes.Length; i++)
            {
                if (infos[firstInfo + i].ParameterType != parameterTypes[i])
                {
                    return(false);
                }
            }

            return(true);
        }
Ejemplo n.º 5
0
        internal static BindingTarget /*!*/ ResolveOverload(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args, string /*!*/ name,
                                                            IList <OverloadInfo> /*!*/ overloads, SelfCallConvention callConvention, bool implicitProtocolConversions,
                                                            out RubyOverloadResolver /*!*/ resolver)
        {
            resolver = new RubyOverloadResolver(metaBuilder, args, callConvention, implicitProtocolConversions);
            var bindingTarget = resolver.ResolveOverload(name, overloads, NarrowingLevel.None, NarrowingLevel.All);

            bool calleeHasBlockParam = bindingTarget.Success && HasBlockParameter(bindingTarget.Overload);

            // At runtime the BlockParam is created with a new RFC instance that identifies the library method frame as
            // a proc-converter target of a method unwinder triggered by break from a block.
            if (args.Signature.HasBlock && calleeHasBlockParam)
            {
                metaBuilder.ControlFlowBuilder = RuleControlFlowBuilder;
            }

            // add restrictions used for overload resolution:
            resolver.AddArgumentRestrictions(metaBuilder, bindingTarget);

            return(bindingTarget);
        }
Ejemplo n.º 6
0
        private DynamicMetaObject InteropBind(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args)
        {
            // TODO: argument count limit depends on the binder!

            // TODO: pass block as the last (before RHS arg?) parameter/ignore block if args not accepting block:
            var normalizedArgs = RubyOverloadResolver.NormalizeArguments(metaBuilder, args, 0, Int32.MaxValue);

            if (!metaBuilder.Error)
            {
                MethodInfo postConverter;
                var        interopBinder = GetInteropBinder(args.RubyContext, normalizedArgs, out postConverter);
                if (interopBinder != null)
                {
                    Type resultType;
                    var  result = interopBinder.Bind(args.MetaTarget, ArrayUtils.MakeArray(normalizedArgs));

                    metaBuilder.SetMetaResult(result, args);
                    if (postConverter != null)
                    {
                        // TODO: do better?
                        var paramType = postConverter.GetParameters()[0].ParameterType;

                        metaBuilder.Result = Ast.Call(null, postConverter, AstUtils.Convert(metaBuilder.Result, paramType));
                        resultType         = postConverter.ReturnType;
                    }
                    else
                    {
                        resultType = interopBinder.ReturnType;
                    }

                    return(metaBuilder.CreateMetaObject(interopBinder, resultType));
                }
                else
                {
                    // interop protocol not supported for this binder -> ignore IDO and treat it as a CLR object:
                    return(null);
                }
            }
            return(metaBuilder.CreateMetaObject(this));
        }
Ejemplo n.º 7
0
        internal override void BuildCallNoFlow(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args, string /*!*/ name)
        {
            Expression instance = _fieldInfo.IsStatic ? null : Ast.Convert(args.TargetExpression, _fieldInfo.DeclaringType);

            if (_isSetter)
            {
                var actualArgs = RubyOverloadResolver.NormalizeArguments(metaBuilder, args, 1, 1);
                if (!metaBuilder.Error)
                {
                    metaBuilder.Result = Ast.Assign(
                        Ast.Field(instance, _fieldInfo),
                        Converter.ConvertExpression(
                            actualArgs[0].Expression,
                            _fieldInfo.FieldType,
                            args.RubyContext,
                            args.MetaContext.Expression,
                            true
                            )
                        );
                }
            }
            else
            {
                RubyOverloadResolver.NormalizeArguments(metaBuilder, args, 0, 0);
                if (!metaBuilder.Error)
                {
                    if (_fieldInfo.IsLiteral)
                    {
                        // TODO: seems like Compiler should correctly handle the literal field case
                        // (if you emit a read to a literal field, you get a NotSupportedExpception from
                        // FieldHandle when we try to emit)
                        metaBuilder.Result = AstUtils.Constant(_fieldInfo.GetValue(null));
                    }
                    else
                    {
                        metaBuilder.Result = Ast.Field(instance, _fieldInfo);
                    }
                }
            }
        }
Ejemplo n.º 8
0
        internal override void BuildMethodMissingCallNoFlow(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args, string /*!*/ name)
        {
            var globalScope = args.TargetClass.GlobalScope;
            var context     = globalScope.Context;

            if (name.LastCharacter() == '=')
            {
                var normalizedArgs = RubyOverloadResolver.NormalizeArguments(metaBuilder, args, 1, 1);
                if (!metaBuilder.Error)
                {
                    var scopeVar = metaBuilder.GetTemporary(typeof(Scope), "#scope");

                    metaBuilder.AddInitialization(
                        Ast.Assign(scopeVar, Methods.GetGlobalScopeFromScope.OpCall(AstUtils.Convert(args.MetaScope.Expression, typeof(RubyScope))))
                        );

                    var interopSetter = context.MetaBinderFactory.InteropSetMember(name.Substring(0, name.Length - 1));

                    metaBuilder.SetMetaResult(
                        interopSetter.Bind(
                            new DynamicMetaObject(
                                scopeVar,
                                BindingRestrictions.Empty,
                                globalScope.Scope
                                ),
                            new[] { normalizedArgs[0] }
                            ),
                        true
                        );
                }
            }
            else
            {
                RubyOverloadResolver.NormalizeArguments(metaBuilder, args, 0, 0);
                Expression errorExpr = metaBuilder.Error ? Ast.Throw(metaBuilder.Result, typeof(object)) : null;

                var scopeVar             = metaBuilder.GetTemporary(typeof(Scope), "#scope");
                var scopeLookupResultVar = metaBuilder.GetTemporary(typeof(object), "#result");

                metaBuilder.AddInitialization(
                    Ast.Assign(scopeVar, Methods.GetGlobalScopeFromScope.OpCall(AstUtils.Convert(args.MetaScope.Expression, typeof(RubyScope))))
                    );

                Expression scopeLookupResultExpr = errorExpr ?? scopeLookupResultVar;
                Expression fallbackExp;

                if (name == "scope")
                {
                    fallbackExp = errorExpr ?? args.TargetExpression;
                }
                else
                {
                    // super(methodName, ...args...) - ignore argument error:
                    args.InsertMethodName(name);
                    fallbackExp = AstUtils.LightDynamic(
                        context.MetaBinderFactory.Call(Symbols.MethodMissing,
                                                       new RubyCallSignature(
                                                           args.Signature.ArgumentCount + 1,
                                                           args.Signature.Flags | RubyCallFlags.HasImplicitSelf | RubyCallFlags.IsSuperCall
                                                           )
                                                       ),
                        typeof(object),
                        args.GetCallSiteArguments(args.TargetExpression)
                        );
                }

                var scopeLookup = Ast.NotEqual(
                    Ast.Assign(scopeLookupResultVar, AstUtils.LightDynamic(context.MetaBinderFactory.InteropTryGetMemberExact(name), typeof(object), scopeVar)),
                    Expression.Constant(OperationFailed.Value)
                    );

                string unmanagled = RubyUtils.TryUnmangleMethodName(name);
                if (unmanagled != null)
                {
                    scopeLookup = Ast.OrElse(
                        scopeLookup,
                        Ast.NotEqual(
                            Ast.Assign(scopeLookupResultVar, AstUtils.LightDynamic(context.MetaBinderFactory.InteropTryGetMemberExact(unmanagled), typeof(object), scopeVar)),
                            Expression.Constant(OperationFailed.Value)
                            )
                        );
                }

                metaBuilder.Result = Ast.Condition(
                    scopeLookup,
                    scopeLookupResultExpr,
                    fallbackExp
                    );
            }
        }
Ejemplo n.º 9
0
        internal static BindingTarget/*!*/ ResolveOverload(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args, string/*!*/ name,
            IList<OverloadInfo>/*!*/ overloads, SelfCallConvention callConvention, bool implicitProtocolConversions, 
            out RubyOverloadResolver/*!*/ resolver) {

            resolver = new RubyOverloadResolver(metaBuilder, args, callConvention, implicitProtocolConversions);
            var bindingTarget = resolver.ResolveOverload(name, overloads, NarrowingLevel.None, NarrowingLevel.All);

            bool calleeHasBlockParam = bindingTarget.Success && HasBlockParameter(bindingTarget.Overload);
            
            // At runtime the BlockParam is created with a new RFC instance that identifies the library method frame as 
            // a proc-converter target of a method unwinder triggered by break from a block.
            if (args.Signature.HasBlock && calleeHasBlockParam) {
                metaBuilder.ControlFlowBuilder = RuleControlFlowBuilder;
            }

            // add restrictions used for overload resolution:
            resolver.AddArgumentRestrictions(metaBuilder, bindingTarget);
            
            return bindingTarget;
        }
Ejemplo n.º 10
0
        public void OverloadResolution_Numeric1() {
            var metaBuilder = new MetaObjectBuilder(null);
            Context.ObjectClass.SetConstant("X", Context.GetClass(typeof(Overloads1.X)));

            object c = Engine.Execute(@"class C < X; new; end");
            var sym = SymbolTable.StringToId("x");
            var ms = MutableString.CreateAscii("x");

            var cases = new[] {
                // F
                new { Args = new[] { MO(1) }, Overloads = "F*", Result = "F1" },
                new { Args = new[] { MO((byte)1) }, Overloads = "F*", Result = "F1" },
                new { Args = new[] { MO(1L) }, Overloads = "F*", Result = "F2" },
                new { Args = new[] { MO(1.2F) }, Overloads = "F*", Result = "F3" },

                // G
                new { Args = new[] { MO(1) }, Overloads = "G*", Result = "G1" },
                new { Args = new[] { MO((byte)1) }, Overloads = "G*", Result = "G1" },
                new { Args = new[] { MO(1L) }, Overloads = "G*", Result = "G2" },
                new { Args = new[] { MO(1.2F) }, Overloads = "G*", Result = "G3" },
                new { Args = new[] { MO(c) }, Overloads = "G*", Result = "G1" },

                // I
                new { Args = new[] { MO(c) }, Overloads = "I*", Result = "I3" },

                // J
                new { Args = new[] { MO(1) }, Overloads = "J*", Result = "J1" },
                new { Args = new[] { MO((BigInteger)1000) }, Overloads = "J*", Result = "J2" },
                new { Args = new[] { MO((byte)12) }, Overloads = "J*", Result = "J1" },
                new { Args = new[] { MO(c) }, Overloads = "J*", Result = "J3" },
                new { Args = new[] { MO(1.0) }, Overloads = "J*", Result = "J3" },
      
                // K
                new { Args = new[] { MO(1) }, Overloads = "K*", Result = "K2" },
                new { Args = new[] { MO(c) }, Overloads = "K*", Result = "K1" },
                new { Args = new[] { MO("x") }, Overloads = "K*", Result = "K1" },

                // L
                new { Args = new[] { MO(sym), MO(sym) }, Overloads = "L*", Result = "L1" },
                new { Args = new[] { MO("x"), MO(sym) }, Overloads = "L*", Result = "L2" },
                new { Args = new[] { MO(ms), MO(sym) }, Overloads = "L*", Result = "L3" },
                new { Args = new[] { MO(null), MO(sym) }, Overloads = "L*", Result = "L3" },
                new { Args = new[] { MO(c), MO(sym) }, Overloads = "L*", Result = "L3" },
            };

            for (int i = 0; i < cases.Length; i++) {
                var args = new CallArguments(Context, MO(new Overloads1()), cases[i].Args, RubyCallSignature.Simple(cases[i].Args.Length));
                var resolver = new RubyOverloadResolver(metaBuilder, args, SelfCallConvention.SelfIsInstance, false);
                var overloads = GetInstanceMethods(typeof(Overloads1), cases[i].Overloads);
                var result = resolver.ResolveOverload(i.ToString(), overloads, NarrowingLevel.None, NarrowingLevel.All);

                Assert(result.Success && result.Method.Name == cases[i].Result);
            }
        }
Ejemplo n.º 11
0
        internal static BindingTarget/*!*/ ResolveOverload(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args, string/*!*/ name,
            IList<MethodBase>/*!*/ overloads, SelfCallConvention callConvention, out RubyOverloadResolver/*!*/ resolver) {

            resolver = new RubyOverloadResolver(metaBuilder, args, callConvention);
            var bindingTarget = resolver.ResolveOverload(name, overloads, NarrowingLevel.None, NarrowingLevel.All);

            bool calleeHasBlockParam = bindingTarget.Success && HasBlockParameter(bindingTarget.Method);
            
            // At runtime the BlockParam is created with a new RFC instance that identifies the library method frame as 
            // a proc-converter target of a method unwinder triggered by break from a block.
            if (args.Signature.HasBlock) {
                var metaBlock = args.GetMetaBlock();
                if (metaBlock.Value != null && calleeHasBlockParam) {
                    Debug.Assert(metaBuilder.BfcVariable != null);
                    metaBuilder.ControlFlowBuilder = RuleControlFlowBuilder;
                }

                // Overload resolution might not need to distinguish between nil and non-nil block.
                // However, we still do since we construct CF only for non-nil blocks.
                if (metaBlock.Value == null) {
                    metaBuilder.AddRestriction(Ast.Equal(metaBlock.Expression, AstUtils.Constant(null)));
                } else {
                    // don't need to test the exact type of the Proc since the code is subclass agnostic:
                    metaBuilder.AddRestriction(Ast.NotEqual(metaBlock.Expression, AstUtils.Constant(null)));
                }
            }

            // add restrictions used for overload resolution:
            resolver.AddArgumentRestrictions(metaBuilder, bindingTarget);
            
            return bindingTarget;
        }