Wraps the arguments of a dynamic call site Includes the actual arguments, the expressions that produced those arguments, and the call signature. These three things are grouped together to ensure that they are all in sync when we want to shift the arguments around during the method binding process.
コード例 #1
0
ファイル: RubyMetaBinder.cs プロジェクト: jcteague/ironruby
        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 = ((IInteropBinder)interopBinder).ResultType;
                    }

                    return metaBuilder.CreateMetaObject(interopBinder, resultType);
                } else {
                    metaBuilder.SetError(Ast.New(
                       typeof(NotSupportedException).GetConstructor(new[] { typeof(string) }),
                       Ast.Constant(String.Format("{0} not supported on foreign meta-objects", this))
                    ));
                }
            }
            return metaBuilder.CreateMetaObject(this);
        }
コード例 #2
0
ファイル: RubyFieldInfo.cs プロジェクト: rudimk/dlr-dotnet
        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);
                    }
                }
            }
        }
コード例 #3
0
        protected override bool Build(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args, bool defaultFallback) {
            if (TryImplicitConversion(metaBuilder, args)) {
                metaBuilder.AddObjectTypeRestriction(args.Target, args.TargetExpression);
                return true;
            }

            // TODO: this is our meta object, should we add IRubyMetaConvertible interface instead of using interop-binder?
            if (args.Target is IDynamicMetaObjectProvider) {
                metaBuilder.SetMetaResult(args.MetaTarget.BindConvert(new InteropBinder.Convert(args.RubyContext, _type, true)), false);
                return true;
            }

            if (defaultFallback) {
                metaBuilder.AddObjectTypeRestriction(args.Target, args.TargetExpression);

                metaBuilder.SetError(Methods.MakeTypeConversionError.OpCall(
                    args.MetaContext.Expression,
                    AstUtils.Convert(args.TargetExpression, typeof(object)),
                    Ast.Constant(_type)
                ));
                return true;
            }

            return false;
        }
コード例 #4
0
 internal override void BuildCallNoFlow(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args, string/*!*/ name) {
     metaBuilder.Result = Methods.GetInstanceVariable.OpCall(
         args.ScopeExpression,
         AstFactory.Box(args.TargetExpression),
         AstUtils.Constant(InstanceVariableName)
     );
 }
コード例 #5
0
 internal override void BuildCallNoFlow(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args, string/*!*/ name) {
     Proc.BuildCall(
         metaBuilder,
         AstUtils.Constant(_lambda),            // proc object
         args.TargetExpression,                 // self
         args
     );
 }
コード例 #6
0
 internal RubyOverloadResolver(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args, SelfCallConvention callConvention,
     bool implicitProtocolConversions)
     : base(args.RubyContext.Binder) {
     _args = args;
     _metaBuilder = metaBuilder;
     _callConvention = callConvention;
     _implicitProtocolConversions = implicitProtocolConversions;
 }
コード例 #7
0
        protected override bool Build(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args, bool defaultFallback) {
            // TODO: this is our meta object, should we add IRubyMetaConvertible interface instead of using interop-binder?
            if (args.Target is IDynamicMetaObjectProvider) {
                metaBuilder.SetMetaResult(args.MetaTarget.BindConvert(new InteropBinder.Convert(args.RubyContext, _type, true)), false);
                return true;
            }

            return BuildConversion(metaBuilder, args.MetaTarget, args.MetaContext.Expression, _type, defaultFallback);
        }
コード例 #8
0
 internal override void BuildCallNoFlow(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args, string/*!*/ name) {
     var visibleOverloads = GetVisibleOverloads(args, MethodBases, false);
     if (visibleOverloads.Count == 0) {
         metaBuilder.SetError(Methods.MakeClrProtectedMethodCalledError.OpCall(
             args.MetaContext.Expression, args.MetaTarget.Expression, Ast.Constant(name)
         ));
     } else {
         BuildCallNoFlow(metaBuilder, args, name, visibleOverloads, CallConvention, ImplicitProtocolConversions);
     }
 }
コード例 #9
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)
         );
     }
 }
コード例 #10
0
ファイル: SuperCallAction.cs プロジェクト: bclubb/ironruby
        protected override bool Build(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args, bool defaultFallback) {
            RubyModule currentDeclaringModule;
            string currentMethodName;

            var scope = args.Scope;

            object target;
            scope.GetSuperCallTarget(out currentDeclaringModule, out currentMethodName, out target);

            var targetExpression = metaBuilder.GetTemporary(typeof(object), "#super-self");
            
            metaBuilder.AddCondition(
                Methods.IsSuperCallTarget.OpCall(
                    AstUtils.Convert(args.MetaScope.Expression, typeof(RubyScope)),
                    AstUtils.Constant(currentDeclaringModule),
                    AstUtils.Constant(currentMethodName),
                    targetExpression
                )
            );

            args.SetTarget(targetExpression, target);

            Debug.Assert(currentDeclaringModule != null);

            RubyMemberInfo method;
            RubyMemberInfo methodMissing = null;

            // we need to lock the hierarchy of the target class:
            var targetClass = scope.RubyContext.GetImmediateClassOf(target);
            using (targetClass.Context.ClassHierarchyLocker()) {
                // initialize all methods in ancestors:                
                targetClass.InitializeMethodsNoLock();

                // target is stored in a local, therefore it cannot be part of the restrictions:
                metaBuilder.TreatRestrictionsAsConditions = true;
                metaBuilder.AddTargetTypeTest(target, targetClass, targetExpression, args.MetaContext, 
                    new[] { Symbols.MethodMissing } // currentMethodName is resolved for super, which cannot be an instance singleton
                );
                metaBuilder.TreatRestrictionsAsConditions = false;

                method = targetClass.ResolveSuperMethodNoLock(currentMethodName, currentDeclaringModule).InvalidateSitesOnOverride().Info;
                if (method == null) {
                    // MRI: method_missing is called for the targetClass, not for the super:
                    methodMissing = targetClass.ResolveMethodMissingForSite(currentMethodName, RubyMethodVisibility.None);
                }
            }

            if (method != null) {
                method.BuildSuperCall(metaBuilder, args, currentMethodName, currentDeclaringModule);
            } else {
                return RubyCallAction.BuildMethodMissingCall(metaBuilder, args, currentMethodName, methodMissing, RubyMethodVisibility.None, true, defaultFallback);
            }

            return true;
        }
コード例 #11
0
        internal override void BuildCallNoFlow(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args, string/*!*/ name) {

            var actualArgs = RubyMethodGroupInfo.MakeActualArgs(metaBuilder, args, true, false, false, false);

            metaBuilder.Result = Methods.SetInstanceVariable.OpCall(
                AstFactory.Box(actualArgs[0]),
                AstFactory.Box(actualArgs[1]),
                args.ScopeExpression,
                AstUtils.Constant(InstanceVariableName)
            );
        }
コード例 #12
0
        internal override void BuildCallNoFlow(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args, string/*!*/ name) {
            Debug.Assert(!args.Signature.HasBlock);

            Proc.SetProcCallRule(
                metaBuilder,
                Ast.Constant(_lambda),            // proc object
                args.TargetExpression,            // self
                Ast.Constant(this),               // this method for super and class_eval
                args
            );
        }
コード例 #13
0
ファイル: RubyMetaBinder.cs プロジェクト: jcteague/ironruby
        public override DynamicMetaObject/*!*/ Bind(DynamicMetaObject/*!*/ scopeOrContextOrTarget, DynamicMetaObject/*!*/[]/*!*/ args) {
            var callArgs = new CallArguments(_context, scopeOrContextOrTarget, args, Signature);
            var metaBuilder = new MetaObjectBuilder(this, args);

            if (IsForeignMetaObject(callArgs.MetaTarget)) {
                return InteropBind(metaBuilder, callArgs);
            } 

            Build(metaBuilder, callArgs, true);
            return metaBuilder.CreateMetaObject(this);
        }
コード例 #14
0
ファイル: RubyAccessorInfo.cs プロジェクト: tnachen/ironruby
 internal override void BuildCallNoFlow(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args, string/*!*/ name) {
     var actualArgs = RubyMethodGroupInfo.NormalizeArguments(metaBuilder, args, SelfCallConvention.NoSelf, false, false);
     if (actualArgs.Length == 0) {
         metaBuilder.Result = Methods.GetInstanceVariable.OpCall(
             args.ScopeExpression,
             AstFactory.Box(args.TargetExpression),
             AstUtils.Constant(InstanceVariableName)
         );
     } else {
         metaBuilder.SetWrongNumberOfArgumentsError(actualArgs.Length, 0);
     }
 }
コード例 #15
0
ファイル: RubyMetaBinder.cs プロジェクト: tnachen/ironruby
        public override DynamicMetaObject/*!*/ Bind(DynamicMetaObject/*!*/ context, DynamicMetaObject/*!*/[]/*!*/ args) {
            var callArgs = new CallArguments(context, args, Signature);
            
            // TODO: COM interop
            if (IsForeignMetaObject(callArgs.MetaTarget)) {
                return InteropBind(callArgs);
            }

            var metaBuilder = new MetaObjectBuilder();
            Build(metaBuilder, callArgs);
            return metaBuilder.CreateMetaObject(this);
        }
コード例 #16
0
ファイル: RubyEventInfo.cs プロジェクト: mscottford/ironruby
 internal override void BuildCallNoFlow(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args, string/*!*/ name) {
     if (args.Signature.HasBlock) {
         metaBuilder.Result = Methods.HookupEvent.OpCall(
             Ast.Convert(Ast.Constant(_eventInfo), typeof(EventInfo)),
             args.TargetExpression,
             Ast.Convert(args.GetBlockExpression(), typeof(Proc))
         );
     } else {
         // TODO: make error
         throw new NotImplementedError("no block given");
     }
 }
コード例 #17
0
ファイル: RubyMethod.cs プロジェクト: jcteague/ironruby
        internal void BuildInvoke(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args) {
            Assert.NotNull(metaBuilder, args);
            Debug.Assert(args.Target == this);

            // TODO: we could compare infos here:
            // first argument must be this method:
            metaBuilder.AddRestriction(Ast.Equal(args.TargetExpression, AstUtils.Constant(this)));

            // set the target (becomes self in the called method):
            args.SetTarget(AstUtils.Constant(_target), _target);

            _info.BuildCall(metaBuilder, args, _name);
        }
コード例 #18
0
ファイル: InteropBinder.cs プロジェクト: toddb/ironruby
            public static DynamicMetaObject/*!*/ Bind(InvokeBinder/*!*/ binder,
                RubyMetaObject/*!*/ target, DynamicMetaObject/*!*/[]/*!*/ args, Action<MetaObjectBuilder, CallArguments>/*!*/ buildInvoke) {

                RubyCallSignature callSignature;
                if (RubyCallSignature.TryCreate(binder.CallInfo, out callSignature)) {
                    return binder.FallbackInvoke(target, args);
                }

                var callArgs = new CallArguments(target.CreateMetaContext(), target, args, callSignature);
                var metaBuilder = new MetaObjectBuilder(target, args);

                buildInvoke(metaBuilder, callArgs);
                return metaBuilder.CreateMetaObject(binder);
            }
コード例 #19
0
        // Only used if method_missing() is called directly on the main singleton.
        internal override void BuildCallNoFlow(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args, string/*!*/ name) {
            var globalScope = args.TargetClass.GlobalScope;

            // TODO: this just calls super for now, so it doesn't look up the scope:
            metaBuilder.Result = AstUtils.LightDynamic(
                new RubyCallAction(globalScope.Context, Symbols.MethodMissing,
                    new RubyCallSignature(
                        args.Signature.ArgumentCount,
                        args.Signature.Flags | RubyCallFlags.HasImplicitSelf | RubyCallFlags.IsSuperCall
                    )
                ),
                typeof(object),
                args.GetCallSiteArguments(args.TargetExpression)
            );
        }
コード例 #20
0
ファイル: ConvertToSAction.cs プロジェクト: TerabyteX/main
        internal static void BuildConversion(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args)
        {
            const string ToS = "to_s";

            if (TryImplicitConversion(metaBuilder, args)) {
                metaBuilder.AddTypeRestriction(args.Target.GetType(), args.TargetExpression);
                return;
            }

            RubyMemberInfo conversionMethod, methodMissing = null;

            RubyClass targetClass = args.RubyContext.GetImmediateClassOf(args.Target);
            using (targetClass.Context.ClassHierarchyLocker()) {
                metaBuilder.AddTargetTypeTest(args.Target, targetClass, args.TargetExpression, args.MetaContext,
                    new[] { ToS, Symbols.MethodMissing }
                );

                conversionMethod = targetClass.ResolveMethodForSiteNoLock(ToS, VisibilityContext.AllVisible).Info;

                // find method_missing - we need to add "to_s" method to the missing methods table:
                if (conversionMethod == null) {
                    methodMissing = targetClass.ResolveMethodMissingForSite(ToS, RubyMethodVisibility.None);
                }
            }

            // invoke target.to_s and if successful convert the result to string unless it is already:
            if (conversionMethod != null) {
                conversionMethod.BuildCall(metaBuilder, args, ToS);
            } else {
                RubyCallAction.BuildMethodMissingCall(metaBuilder, args, ToS, methodMissing, RubyMethodVisibility.None, false, true);
            }

            if (metaBuilder.Error) {
                return;
            }

            metaBuilder.Result = Methods.ToSDefaultConversion.OpCall(
                AstUtils.Convert(args.MetaContext.Expression, typeof(RubyContext)),
                AstUtils.Box(args.TargetExpression),
                AstUtils.Box(metaBuilder.Result)
            );
        }
コード例 #21
0
ファイル: RubyEventInfo.cs プロジェクト: jxnmaomao/ironruby
 internal override void BuildCallNoFlow(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args, string/*!*/ name) {
     // TODO: splat, rhs, ...
     if (args.Signature.ArgumentCount == 0) {
         if (args.Signature.HasBlock) {
             metaBuilder.Result = Methods.HookupEvent.OpCall(
                 AstUtils.Constant(this),
                 args.TargetExpression,
                 Ast.Convert(args.GetBlockExpression(), typeof(Proc))
             );
         } else {
             metaBuilder.Result = Methods.CreateEvent.OpCall(
                 AstUtils.Constant(this),
                 args.TargetExpression,
                 AstUtils.Constant(name)
             );
         }
     } else {
         metaBuilder.SetError(Methods.MakeWrongNumberOfArgumentsError.OpCall(Ast.Constant(args.Signature.ArgumentCount), Ast.Constant(0)));
     }
 }
コード例 #22
0
ファイル: ConvertToSAction.cs プロジェクト: toddb/ironruby
        protected override void Build(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args) {
            const string ToS = "to_s";

            // no conversion for a subclass of string:
            var stringTarget = args.Target as MutableString;
            if (stringTarget != null) {
                metaBuilder.AddTypeRestriction(args.Target.GetType(), args.TargetExpression);
                metaBuilder.Result = AstUtils.Convert(args.TargetExpression, typeof(MutableString));
                return;
            }

            RubyMemberInfo conversionMethod, methodMissing = null;

            RubyClass targetClass = args.RubyContext.GetImmediateClassOf(args.Target);
            using (targetClass.Context.ClassHierarchyLocker()) {
                metaBuilder.AddTargetTypeTest(args.Target, targetClass, args.TargetExpression, args.MetaContext);
                conversionMethod = targetClass.ResolveMethodForSiteNoLock(ToS, RubyClass.IgnoreVisibility).Info;

                // find method_missing - we need to add "to_xxx" methods to the missing methods table:
                if (conversionMethod == null) {
                    methodMissing = targetClass.ResolveMethodMissingForSite(ToS, RubyMethodVisibility.None);
                }
            }
            
            // invoke target.to_s and if successful convert the result to string unless it is already:
            if (conversionMethod != null) {
                conversionMethod.BuildCall(metaBuilder, args, ToS);

                if (metaBuilder.Error) {
                    return;
                }
            } else {
                RubyCallAction.BindToMethodMissing(metaBuilder, args, ToS, methodMissing, RubyMethodVisibility.None, false, true);
            }

            metaBuilder.Result = Methods.ToSDefaultConversion.OpCall(
                AstUtils.Convert(args.MetaContext.Expression, typeof(RubyContext)), 
                AstFactory.Box(args.TargetExpression), 
                AstFactory.Box(metaBuilder.Result)
            );
        }
コード例 #23
0
ファイル: RubyFieldInfo.cs プロジェクト: Hank923/ironruby
        internal override void BuildCallNoFlow(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args, string/*!*/ name) {
            Expression expr = null;
            Expression instance = _fieldInfo.IsStatic ? null : Ast.Convert(args.TargetExpression, _fieldInfo.DeclaringType);

            if (_isSetter) {
                // parameters should be: instance/type, value
                if (args.SimpleArgumentCount == 0 && args.Signature.HasRhsArgument) {
                    expr = Ast.Assign(
                        Ast.Field(instance, _fieldInfo),
                        Converter.ConvertExpression(
                            args.GetRhsArgumentExpression(), 
                            _fieldInfo.FieldType,
                            args.RubyContext, 
                            args.MetaContext.Expression,
                            true
                        )
                    );
                }
            } else {
                // parameter should be: instance/type
                if (args.SimpleArgumentCount == 0) {
                    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)
                        expr = AstUtils.Constant(_fieldInfo.GetValue(null));
                    } else {
                        expr = Ast.Field(instance, _fieldInfo);
                    }
                }
            }

            if (expr != null) {
                metaBuilder.Result = expr;
            } else {
                metaBuilder.SetError(
                    Methods.MakeInvalidArgumentTypesError.OpCall(AstUtils.Constant(_isSetter ? name + "=" : name))
                );
            }
        }
コード例 #24
0
ファイル: RubyCallAction.cs プロジェクト: sipsorcery/IronRuby
        // Returns true if the call was bound (with success or failure), false if fallback should be performed.
        internal static bool BuildAccess(MetaObjectBuilder /*!*/ metaBuilder, string /*!*/ methodName, CallArguments /*!*/ args,
                                         bool defaultFallback, bool callClrMethods)
        {
            RubyMemberInfo methodMissing;
            var            method = Resolve(metaBuilder, methodName, args, out methodMissing);

            if (method.Found)
            {
                if (!callClrMethods && !method.Info.IsRubyMember)
                {
                    return(false);
                }

                if (method.Info.IsDataMember)
                {
                    method.Info.BuildCall(metaBuilder, args, methodName);
                }
                else
                {
                    metaBuilder.Result = Methods.CreateBoundMember.OpCall(
                        AstUtils.Convert(args.TargetExpression, typeof(object)),
                        Ast.Constant(method.Info, typeof(RubyMemberInfo)),
                        Ast.Constant(methodName)
                        );
                }
                return(true);
            }
            else
            {
                // Ruby doesn't have "attribute_missing" so we will always use method_missing and return a bound method object:
                return(BuildMethodMissingAccess(metaBuilder, args, methodName, methodMissing, method.IncompatibleVisibility, false, defaultFallback));
            }
        }
コード例 #25
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(RubyMetaBinderFactory.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(RubyMetaBinderFactory.InteropTryGetMemberExact(unmanagled), typeof(object), scopeVar)),
                            Expression.Constant(OperationFailed.Value)
                        )
                    );
                }

                metaBuilder.Result = Ast.Condition(
                    scopeLookup,
                    scopeLookupResultExpr,
                    fallbackExp
                );
            }
        }
コード例 #26
0
ファイル: RubyCallAction.cs プロジェクト: gaybro8777/ironruby
        /// <exception cref="MissingMethodException">The resolved method is Kernel#method_missing.</exception>
        internal static void Bind(MetaObjectBuilder /*!*/ metaBuilder, string /*!*/ methodName, CallArguments /*!*/ args)
        {
            metaBuilder.AddTargetTypeTest(args);

            RubyMemberInfo method = args.RubyContext.ResolveMethod(args.Target, methodName, true).InvalidateSitesOnOverride();

            if (method != null && RubyModule.IsMethodVisible(method, args.Signature.HasImplicitSelf))
            {
                method.BuildCall(metaBuilder, args, methodName);
            }
            else
            {
                // insert the method name argument into the args
                object symbol = SymbolTable.StringToId(methodName);
                args.InsertSimple(0, new MetaObject(Ast.Constant(symbol), Restrictions.Empty, symbol));

                BindToMethodMissing(metaBuilder, methodName, args, method != null);
            }
        }
コード例 #27
0
ファイル: RubyMemberInfo.cs プロジェクト: rudimk/dlr-dotnet
 internal virtual void BuildMethodMissingCallNoFlow(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args, string /*!*/ name)
 {
     args.InsertMethodName(name);
     BuildCallNoFlow(metaBuilder, args, Symbols.MethodMissing);
 }
コード例 #28
0
ファイル: InteropBinder.cs プロジェクト: joshholmes/ironruby
            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);

                var normalizedArgs = 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);
            }
コード例 #29
0
        protected override bool Build(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args, bool defaultFallback)
        {
            RubyModule currentDeclaringModule;
            string     currentMethodName;

            var scope     = args.Scope;
            var scopeExpr = AstUtils.Convert(args.MetaScope.Expression, typeof(RubyScope));

            RubyScope targetScope;
            int       scopeNesting = scope.GetSuperCallTarget(out currentDeclaringModule, out currentMethodName, out targetScope);

            if (scopeNesting == -1)
            {
                metaBuilder.AddCondition(Methods.IsSuperOutOfMethodScope.OpCall(scopeExpr));
                metaBuilder.SetError(Methods.MakeTopLevelSuperException.OpCall());
                return(true);
            }

            object target           = targetScope.SelfObject;
            var    targetExpression = metaBuilder.GetTemporary(typeof(object), "#super-self");
            var    assignTarget     = Ast.Assign(
                targetExpression,
                Methods.GetSuperCallTarget.OpCall(scopeExpr, AstUtils.Constant(scopeNesting))
                );

            if (_signature.HasImplicitArguments && targetScope.Kind == ScopeKind.BlockMethod)
            {
                metaBuilder.AddCondition(Ast.NotEqual(assignTarget, Ast.Field(null, Fields.NeedsUpdate)));
                metaBuilder.SetError(Methods.MakeImplicitSuperInBlockMethodError.OpCall());
                return(true);
            }

            // If we need to update we return RubyOps.NeedsUpdate instance that will cause the subsequent conditions to fail:
            metaBuilder.AddInitialization(assignTarget);

            args.SetTarget(targetExpression, target);

            Debug.Assert(currentDeclaringModule != null);

            RubyMemberInfo method;
            RubyMemberInfo methodMissing = null;

            // MRI bug: Uses currentDeclaringModule for method look-up so we can end up with an instance method of class C
            // called on a target of another class. See http://redmine.ruby-lang.org/issues/show/2419.

            // we need to lock the hierarchy of the target class:
            var targetClass = scope.RubyContext.GetImmediateClassOf(target);

            using (targetClass.Context.ClassHierarchyLocker()) {
                // initialize all methods in ancestors:
                targetClass.InitializeMethodsNoLock();

                // target is stored in a local, therefore it cannot be part of the restrictions:
                metaBuilder.TreatRestrictionsAsConditions = true;
                metaBuilder.AddTargetTypeTest(target, targetClass, targetExpression, args.MetaContext,
                                              new[] { Symbols.MethodMissing } // currentMethodName is resolved for super, which cannot be an instance singleton
                                              );
                metaBuilder.TreatRestrictionsAsConditions = false;

                method = targetClass.ResolveSuperMethodNoLock(currentMethodName, currentDeclaringModule).InvalidateSitesOnOverride().Info;

                if (_signature.ResolveOnly)
                {
                    metaBuilder.Result = AstUtils.Constant(method != null);
                    return(true);
                }

                if (method == null)
                {
                    // MRI: method_missing is called for the targetClass, not for the super:
                    methodMissing = targetClass.ResolveMethodMissingForSite(currentMethodName, RubyMethodVisibility.None);
                }
            }

            if (method != null)
            {
                method.BuildSuperCall(metaBuilder, args, currentMethodName, currentDeclaringModule);
            }
            else
            {
                return(RubyCallAction.BuildMethodMissingCall(metaBuilder, args, currentMethodName, methodMissing, RubyMethodVisibility.None, true, defaultFallback));
            }

            return(true);
        }
コード例 #30
0
ファイル: RubyCallAction.cs プロジェクト: gaybro8777/ironruby
        internal static void BindToMethodMissing(MetaObjectBuilder /*!*/ metaBuilder, string /*!*/ methodName, CallArguments /*!*/ args, bool privateMethod)
        {
            // args already contain method name:
            var method = args.RubyContext.ResolveMethod(args.Target, Symbols.MethodMissing, true).InvalidateSitesOnOverride();

            // TODO: better check for builtin method
            if (method == null ||
                method.DeclaringModule == args.RubyContext.KernelModule && method is RubyMethodGroupInfo)
            {
                // throw an exception immediately, do not cache the rule:
                if (privateMethod)
                {
                    throw RubyExceptions.CreatePrivateMethodCalled(args.RubyContext, args.Target, methodName);
                }
                else
                {
                    throw RubyExceptions.CreateMethodMissing(args.RubyContext, args.Target, methodName);
                }
            }

            method.BuildCall(metaBuilder, args, methodName);
        }
コード例 #31
0
        /// <summary>
        /// Takes current result and wraps it into try-filter(MethodUnwinder)-finally block that ensures correct "break" behavior for
        /// library method calls with block given in bfcVariable (BlockParam).
        /// </summary>
        public static void RuleControlFlowBuilder(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args)
        {
            if (metaBuilder.Error)
            {
                return;
            }

            var metaBlock = args.GetMetaBlock();

            Debug.Assert(metaBlock != null, "RuleControlFlowBuilder should only be used if the signature has a block");

            // We construct CF only for non-nil blocks thus we need a test for it:
            if (metaBlock.Value == null)
            {
                metaBuilder.AddRestriction(Ast.Equal(metaBlock.Expression, AstUtils.Constant(null)));
                return;
            }

            // 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)));
            Expression bfcVariable = metaBuilder.BfcVariable;

            Debug.Assert(bfcVariable != null);

            // Method call with proc can invoke control flow that returns an arbitrary value from the call, so we need to type result to Object.
            // Otherwise, the result could only be result of targetExpression unless its return type is void.
            Expression          resultVariable = metaBuilder.GetTemporary(typeof(object), "#result");
            ParameterExpression unwinder;

            metaBuilder.Result = Ast.Block(
                Ast.Assign(bfcVariable, Methods.CreateBfcForLibraryMethod.OpCall(AstUtils.Convert(args.GetBlockExpression(), typeof(Proc)))),
                AstUtils.Try(
                    Ast.Assign(resultVariable, AstUtils.Convert(metaBuilder.Result, typeof(object)))
                    ).Filter(unwinder = Ast.Parameter(typeof(MethodUnwinder), "#unwinder"),
                             Methods.IsProcConverterTarget.OpCall(bfcVariable, unwinder),

                             Ast.Assign(resultVariable, Ast.Field(unwinder, MethodUnwinder.ReturnValueField)),
                             AstUtils.Default(typeof(object))
                             ).Finally(
                    Methods.LeaveProcConverter.OpCall(bfcVariable)
                    ),
                resultVariable
                );
        }
コード例 #32
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);
        }
コード例 #33
0
        /// <summary>
        /// Takes current result and wraps it into try-filter(MethodUnwinder)-finally block that ensures correct "break" behavior for
        /// Ruby method calls with a block given in arguments.
        ///
        /// Sets up a RFC frame similarly to MethodDeclaration.
        /// </summary>
        public static void RuleControlFlowBuilder(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args)
        {
            Debug.Assert(args.Signature.HasBlock);
            if (metaBuilder.Error)
            {
                return;
            }

            // TODO (improvement):
            // We don't special case null block here, although we could (we would need a test for that then).
            // We could also statically know (via call-site flag) that the current method is not a proc-converter (passed by ref),
            // which would make such calls faster.
            var rfcVariable    = metaBuilder.GetTemporary(typeof(RuntimeFlowControl), "#rfc");
            var resultVariable = metaBuilder.GetTemporary(typeof(object), "#result");

            MSA.ParameterExpression unwinder;

            metaBuilder.Result = Ast.Block(
                // initialize frame (RFC):
                Ast.Assign(rfcVariable, Methods.CreateRfcForMethod.OpCall(AstUtils.Convert(args.GetBlockExpression(), typeof(Proc)))),
                AstUtils.Try(
                    Ast.Assign(resultVariable, metaBuilder.Result)
                    ).Filter(unwinder = Ast.Parameter(typeof(MethodUnwinder), "#unwinder"),
                             Ast.Equal(Ast.Field(unwinder, MethodUnwinder.TargetFrameField), rfcVariable),

                             // return unwinder.ReturnValue;
                             Ast.Assign(resultVariable, Ast.Field(unwinder, MethodUnwinder.ReturnValueField))

                             ).Finally(
                    // we need to mark the RFC dead snce the block might escape and break later:
                    Methods.LeaveMethodFrame.OpCall(rfcVariable)
                    ),
                resultVariable
                );
        }
コード例 #34
0
 internal override void BuildCallNoFlow(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args, string /*!*/ name)
 {
     BuildCallNoFlow(metaBuilder, args, name, MethodBases, CallConvention, ImplicitProtocolConversions);
 }
コード例 #35
0
 public static void InstanceAllocator(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args, string /*!*/ name)
 {
     ((RubyClass)args.Target).BuildObjectAllocation(metaBuilder, args, name);
 }
コード例 #36
0
 internal override void BuildCallNoFlow(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args, string /*!*/ name)
 {
     _ruleGenerator(metaBuilder, args, name);
 }
コード例 #37
0
ファイル: RubyMemberInfo.cs プロジェクト: rudimk/dlr-dotnet
 internal void BuildMethodMissingCall(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args, string /*!*/ name)
 {
     BuildMethodMissingCallNoFlow(metaBuilder, args, name);
     metaBuilder.BuildControlFlow(args);
 }
コード例 #38
0
ファイル: RubyCallAction.cs プロジェクト: sipsorcery/IronRuby
        // Returns true if the call was bound (with success or failure), false if fallback should be performed.
        internal static bool BuildCall(MetaObjectBuilder /*!*/ metaBuilder, string /*!*/ methodName, CallArguments /*!*/ args,
                                       bool defaultFallback, bool callClrMethods)
        {
            RubyMemberInfo methodMissing;
            var            method = Resolve(metaBuilder, methodName, args, out methodMissing);

            if (method.Found)
            {
                if (!callClrMethods && !method.Info.IsRubyMember)
                {
                    return(false);
                }

                if (args.Signature.ResolveOnly)
                {
                    metaBuilder.Result = AstFactory.True;
                    return(true);
                }

                if (args.Signature.IsVirtualCall && !method.Info.IsRubyMember)
                {
                    metaBuilder.Result = Ast.Field(null, Fields.ForwardToBase);
                    return(true);
                }

                method.Info.BuildCall(metaBuilder, args, methodName);
                return(true);
            }
            else if (args.Signature.ResolveOnly)
            {
                metaBuilder.Result = AstFactory.False;
                return(true);
            }
            else
            {
                return(BuildMethodMissingCall(metaBuilder, args, methodName, methodMissing, method.IncompatibleVisibility, false, defaultFallback));
            }
        }
コード例 #39
0
        private void AddBlockArguments(MetaObjectBuilder/*!*/ rule, List<Expression>/*!*/ actualArgs, CallArguments/*!*/ args, int parameterIndex) {

            while (parameterIndex < args.Length) {
                switch (args.GetArgumentKind(parameterIndex)) {
                    case ArgumentKind.Simple:
                        actualArgs.Add(args.Expressions[parameterIndex]);
                        break;

                    case ArgumentKind.List:
                        ArgsBuilder.SplatListToArguments(rule, actualArgs, args.Values[parameterIndex], args.Expressions[parameterIndex], false);
                        break;

                    case ArgumentKind.Instance:
                    case ArgumentKind.Block:
                    default:
                        throw new NotImplementedException();
                }

                parameterIndex++;
            }
        }
コード例 #40
0
ファイル: RubyCallAction.cs プロジェクト: sipsorcery/IronRuby
 protected override bool Build(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args, bool defaultFallback)
 {
     return(BuildCall(metaBuilder, _methodName, args, defaultFallback, true));
 }
コード例 #41
0
ファイル: InteropBinder.cs プロジェクト: joshholmes/ironruby
            internal static DynamicMetaObject FallbackInvokeMember(IInteropBinder/*!*/ binder, string/*!*/ methodName, CallInfo/*!*/ callInfo,
                DynamicMetaObject/*!*/ target, DynamicMetaObject/*!*/[]/*!*/ args, DynamicMetaObject errorSuggestion) {

                var metaBuilder = new MetaObjectBuilder(binder, target, args);
                var callArgs = new CallArguments(binder.Context, target, args, callInfo);

                if (!RubyCallAction.BuildCall(metaBuilder, methodName, callArgs, errorSuggestion == null, true)) {
                    Debug.Assert(errorSuggestion != null);
                    // method wasn't found so we didn't do any operation with arguments that would require restrictions converted to conditions:
                    metaBuilder.SetMetaResult(errorSuggestion, false);
                }

                return metaBuilder.CreateMetaObject((DynamicMetaObjectBinder)binder);
            }
コード例 #42
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
                    );
            }
        }
コード例 #43
0
ファイル: InteropBinder.cs プロジェクト: joshholmes/ironruby
            public static DynamicMetaObject/*!*/ Bind(DynamicMetaObject/*!*/ context, GetMemberBinder/*!*/ binder, DynamicMetaObject/*!*/ target, 
                Func<DynamicMetaObject, DynamicMetaObject>/*!*/ fallback) {
                Debug.Assert(fallback != null);

                var callArgs = new CallArguments(context, target, DynamicMetaObject.EmptyMetaObjects, RubyCallSignature.Interop(0));
                var metaBuilder = new MetaObjectBuilder(target);

                if (!RubyCallAction.BuildAccess(metaBuilder, binder.Name, callArgs, false, false)) {
                    metaBuilder.SetMetaResult(fallback(target), false);
                }

                return metaBuilder.CreateMetaObject(binder);
            }
コード例 #44
0
        internal static IList <OverloadInfo> /*!*/ GetVisibleOverloads(CallArguments /*!*/ args, IList <OverloadInfo> /*!*/ overloads, bool isSuperCall)
        {
            IList <OverloadInfo> newOverloads = null;

            Debug.Assert(overloads.Count > 0);

            // handle CLR-protected and virtual methods:

            // TODO (opt):
            // We might be able to cache the callable overloads in a MethodGroup.
            // However, the _overloadOwners of that group would need to point to the original overload owners, not the current class, in order
            // to preserve semantics of overload deletion/redefinition (deletion of the protected overload would need to imply deletion
            // of the correpsondig public overload in the cached MethodGroup).
            if (isSuperCall || !args.RubyContext.DomainManager.Configuration.PrivateBinding)
            {
                Type         underlyingType = null;
                BindingFlags bindingFlags   = 0;

                for (int i = 0; i < overloads.Count; i++)
                {
                    var overload = overloads[i];
                    if ((isSuperCall && overload.IsVirtual && !overload.IsFinal) || overload.IsProtected)
                    {
                        if (newOverloads == null)
                        {
                            newOverloads = CollectionUtils.GetRange(overloads, 0, i);

                            RubyClass cls;
                            IRubyType rt = args.Target as IRubyType;
                            if (rt != null)
                            {
                                bindingFlags   = BindingFlags.Instance;
                                underlyingType = args.Target.GetType();
                            }
                            else if ((cls = args.Target as RubyClass) != null && cls.IsRubyClass && !cls.IsSingletonClass)
                            {
                                bindingFlags   = BindingFlags.Static;
                                underlyingType = cls.GetUnderlyingSystemType();
                            }
                        }

                        if (underlyingType != null)
                        {
                            // TODO (opt): we can define a method on the emitted type that does this more efficently:
                            IList <Type> genericArguments = overload.IsGenericMethod ? overload.GenericArguments : null;

                            OverloadInfo visibleMethod = GetMethodOverload(
                                ArrayUtils.ToArray(overload.Parameters, (pi) => pi.ParameterType),
                                genericArguments,
                                underlyingType,
#if FEATURE_REFEMIT // TODO: should we always prefix with #base# ???
                                ClsTypeEmitter.BaseMethodPrefix + overload.Name,
#else
                                overload.Name,
#endif
                                BindingFlags.Public | bindingFlags
                                );

                            Debug.Assert(visibleMethod != null);

                            newOverloads.Add(visibleMethod);
                        }
                    }
                    else if (newOverloads != null)
                    {
                        newOverloads.Add(overload);
                    }
                }
            }

            return(newOverloads ?? overloads);
        }
コード例 #45
0
ファイル: RubyMemberInfo.cs プロジェクト: rudimk/dlr-dotnet
 internal virtual void BuildCallNoFlow(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args, string /*!*/ name)
 {
     throw Assert.Unreachable;
 }
コード例 #46
0
        private void SetCallRuleArguments(
            Expression/*!*/ blockParameterExpression, // special arg #0
            Expression/*!*/ selfParameterExpression,  // special arg #1
            CallArguments/*!*/ args,                  // user args
            Expression/*!*/ codeContextExpression,
            MetaObjectBuilder/*!*/ rule, 
            ArgsBuilder/*!*/ actualArgs) {

            // mandatory args:
            actualArgs.Add(blockParameterExpression);
            actualArgs.Add(selfParameterExpression);

            int parameterIndex = 0;

            // mimics CompoundLeftValue.TransformWrite //

            // L(1,-)?
            bool leftOneNone = OptionalParamCount == 1 && !HasParamsArray;

            // L(0,*)?
            bool leftNoneSplat = OptionalParamCount == 0 && HasParamsArray;

            // R(0,*)?
            bool rightNoneSplat = !args.Signature.IsSimple && args.Length == 1 && args.GetArgumentKind(0) == ArgumentKind.List;

            // R(1,-)?
            bool rightOneNone = !args.Signature.IsSimple && args.Length == 1 && args.GetArgumentKind(0) == ArgumentKind.Simple
                || args.Signature.IsSimple && args.Length == 1;

            // R(1,*)?
            bool rightOneSplat = !args.Signature.IsSimple && args.Length == 2 &&
                args.GetArgumentKind(0) == ArgumentKind.Simple &&
                args.GetArgumentKind(1) == ArgumentKind.List;

            // R(0,-)?
            bool rightNoneNone = args.Length == 0;

            if (leftOneNone) {
                Expression rvalue;

                if (rightOneNone) {
                    // simple assignment
                    rvalue = args.Expressions[parameterIndex];
                } else if (rightOneSplat && TestEmptyList(rule, args.Values[parameterIndex + 1], args.Expressions[parameterIndex + 1])) {
                    // simple assignment if the splatted value is an empty array:
                    rvalue = args.Expressions[parameterIndex];
                } else if (rightNoneNone) {
                    // nil assignment
                    rvalue = AddWarning(codeContextExpression, Ast.Constant(null));
                } else if (rightNoneSplat) {
                    // Splat(RHS[*]):
                    rvalue = MakeArgumentSplatWithWarning(rule, args.Values[parameterIndex], args.Expressions[parameterIndex], codeContextExpression);
                } else {
                    // more than one argument -> pack to an array + warning

                    // MakeArray(RHS) + SplatAppend(RHS*):
                    List<Expression> arguments = new List<Expression>();
                    AddBlockArguments(rule, arguments, args, parameterIndex);
                    rvalue = AddWarning(codeContextExpression, ArgsBuilder.MakeArgsArray(arguments));
                }

                actualArgs.Add(rvalue);

            } else {

                // R(0,*) || R(1,-) && !L(0,*) ==> CompoundLeftValue.TransformWrite does Unsplat, MakeArray otherwise.
                // 
                // However, we are not constructing a materalized resulting array (contrary to CompoundLeftValue.TransformWrite).
                // The resulting array is comprised of slots on the stack (loaded to the formal parameters of the block #1, ..., #n).
                // Therefore, we effectively need to take items of imaginary Unsplat's result and put them into the actualArgs as arguments.
                //
                // Unsplat of x makes an array containing x if x is not an array, otherwise it returns x.
                // So, we just need to take elements of x and push them onto the stack.
                //

                List<Expression> arguments = new List<Expression>();

                if (rightNoneSplat) {
                    ArgsBuilder.SplatListToArguments(rule, arguments, args.Values[parameterIndex], args.Expressions[parameterIndex], false);
                } else if (rightOneNone && !leftNoneSplat) {
                    ArgsBuilder.SplatListToArguments(rule, arguments, args.Values[parameterIndex], args.Expressions[parameterIndex], true);
                } else {
                    AddBlockArguments(rule, arguments, args, parameterIndex);
                }

                actualArgs.AddRange(arguments);
            }

            actualArgs.AddForEachMissingArgument(delegate() { return Ast.Constant(null); });

            if (HasParamsArray) {
                actualArgs.AddParamsArray();
            }
        }
コード例 #47
0
        internal override void BuildSuperCallNoFlow(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args, string /*!*/ name, RubyModule /*!*/ declaringModule)
        {
            Assert.NotNull(declaringModule, metaBuilder, args);
            var visibleOverloads = GetVisibleOverloads(args, MethodBases, true);

            if (visibleOverloads.Count == 0)
            {
                metaBuilder.SetError(Methods.MakeClrVirtualMethodCalledError.OpCall(
                                         args.MetaContext.Expression, args.MetaTarget.Expression, Ast.Constant(name)
                                         ));
            }
            else
            {
                BuildCallNoFlow(metaBuilder, args, name, visibleOverloads, CallConvention, ImplicitProtocolConversions);
            }
        }
コード例 #48
0
ファイル: InteropBinder.cs プロジェクト: joshholmes/ironruby
            public static DynamicMetaObject/*!*/ Bind(DynamicMetaObject/*!*/ context, string/*!*/ methodName, CallInfo/*!*/ callInfo, 
                DynamicMetaObjectBinder/*!*/ binder, DynamicMetaObject/*!*/ target, DynamicMetaObject/*!*/[]/*!*/ args,
                Func<DynamicMetaObject, DynamicMetaObject[], DynamicMetaObject>/*!*/ fallback) {
                Debug.Assert(fallback != null);

                var callArgs = new CallArguments(context, target, args, RubyCallSignature.Interop(callInfo.ArgumentCount));
                var metaBuilder = new MetaObjectBuilder(target, args);

                if (!RubyCallAction.BuildCall(metaBuilder, methodName, callArgs, false, false)) {
                    metaBuilder.SetMetaResult(fallback(target, args), false);
                }
                return metaBuilder.CreateMetaObject(binder);
            }
コード例 #49
0
ファイル: RubyCallAction.cs プロジェクト: sipsorcery/IronRuby
        private static MethodMissingBinding BindToKernelMethodMissing(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args, string /*!*/ methodName,
                                                                      RubyMemberInfo methodMissing, RubyMethodVisibility incompatibleVisibility, bool isSuperCall)
        {
            // TODO: better specialization of method_missing methods
            if (methodMissing == null ||
                methodMissing.DeclaringModule == methodMissing.Context.KernelModule && methodMissing is RubyLibraryMethodInfo)
            {
                if (isSuperCall)
                {
                    metaBuilder.SetError(Methods.MakeMissingSuperException.OpCall(AstUtils.Constant(methodName)));
                }
                else if (incompatibleVisibility == RubyMethodVisibility.Private)
                {
                    metaBuilder.SetError(Methods.MakePrivateMethodCalledError.OpCall(
                                             AstUtils.Convert(args.MetaContext.Expression, typeof(RubyContext)), args.TargetExpression, AstUtils.Constant(methodName))
                                         );
                }
                else if (incompatibleVisibility == RubyMethodVisibility.Protected)
                {
                    metaBuilder.SetError(Methods.MakeProtectedMethodCalledError.OpCall(
                                             AstUtils.Convert(args.MetaContext.Expression, typeof(RubyContext)), args.TargetExpression, AstUtils.Constant(methodName))
                                         );
                }
                else
                {
                    return(MethodMissingBinding.Fallback);
                }

                return(MethodMissingBinding.Error);
            }

            return(MethodMissingBinding.Custom);
        }
コード例 #50
0
ファイル: InteropBinder.cs プロジェクト: joshholmes/ironruby
            public static DynamicMetaObject/*!*/ Bind(DynamicMetaObject/*!*/ context, SetMemberBinder/*!*/ binder, DynamicMetaObject/*!*/ target,
                DynamicMetaObject/*!*/ value, Func<DynamicMetaObject, DynamicMetaObject, DynamicMetaObject>/*!*/ fallback) {
                Debug.Assert(fallback != null);

                var args = new[] { value };
                var callArgs = new CallArguments(context, target, args, RubyCallSignature.Interop(1));
                var metaBuilder = new MetaObjectBuilder(target, args);

                if (!RubyCallAction.BuildCall(metaBuilder, binder.Name + "=", callArgs, false, false)) {
                    metaBuilder.SetMetaResult(fallback(target, value), false);
                }

                return metaBuilder.CreateMetaObject(binder);
            }
コード例 #51
0
ファイル: RubyCallAction.cs プロジェクト: sipsorcery/IronRuby
        // Returns true if the call was bound (with success or failure), false if fallback should be performed.
        internal static bool BuildMethodMissingAccess(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args, string /*!*/ methodName,
                                                      RubyMemberInfo methodMissing, RubyMethodVisibility incompatibleVisibility, bool isSuperCall, bool defaultFallback)
        {
            switch (BindToKernelMethodMissing(metaBuilder, args, methodName, methodMissing, incompatibleVisibility, isSuperCall))
            {
            case MethodMissingBinding.Custom:
                // we pretend we found the member and return a method that calls method_missing:
                Debug.Assert(!metaBuilder.Error);
                metaBuilder.Result = Methods.CreateBoundMissingMember.OpCall(
                    AstUtils.Convert(args.TargetExpression, typeof(object)),
                    Ast.Constant(methodMissing, typeof(RubyMemberInfo)),
                    Ast.Constant(methodName)
                    );
                return(true);

            case MethodMissingBinding.Error:
                // method_missing is defined in Kernel, error has been reported:
                return(true);

            case MethodMissingBinding.Fallback:
                // method_missing is defined in Kernel:
                if (defaultFallback)
                {
                    metaBuilder.SetError(Methods.MakeMissingMemberError.OpCall(Ast.Constant(methodName)));
                    return(true);
                }
                return(false);
            }
            throw Assert.Unreachable;
        }
コード例 #52
0
 public static void MethodCall(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args, string /*!*/ name)
 {
     ((RubyMethod)args.Target).BuildInvoke(metaBuilder, args);
 }
コード例 #53
0
ファイル: RubyCallAction.cs プロジェクト: sipsorcery/IronRuby
        internal static MethodResolutionResult Resolve(MetaObjectBuilder /*!*/ metaBuilder, string /*!*/ methodName, CallArguments /*!*/ args,
                                                       out RubyMemberInfo methodMissing)
        {
            MethodResolutionResult method;
            var targetClass       = args.TargetClass;
            var visibilityContext = GetVisibilityContext(args.Signature, args.Scope);

            using (targetClass.Context.ClassHierarchyLocker()) {
                metaBuilder.AddTargetTypeTest(args.Target, targetClass, args.TargetExpression, args.MetaContext,
                                              new[] { methodName, Symbols.MethodMissing }
                                              );

                if (args.Signature.IsSuperCall)
                {
                    Debug.Assert(!args.Signature.IsVirtualCall && args.Signature.HasImplicitSelf);
                    method = targetClass.ResolveSuperMethodNoLock(methodName, targetClass).InvalidateSitesOnOverride();
                }
                else
                {
                    var options = args.Signature.IsVirtualCall ? MethodLookup.Virtual : MethodLookup.Default;
                    method = targetClass.ResolveMethodForSiteNoLock(methodName, visibilityContext, options);
                }

                if (!method.Found)
                {
                    methodMissing = targetClass.ResolveMethodMissingForSite(methodName, method.IncompatibleVisibility);
                }
                else
                {
                    methodMissing = null;
                }
            }

            // Whenever the current self's class changes we need to invalidate the rule, if a protected method is being called.
            if (method.Info != null && method.Info.IsProtected && visibilityContext.Class != null)
            {
                // We don't need to compare versions, just the class objects (super-class relationship cannot be changed).
                // Since we don't want to hold on a class object (to make it collectible) we compare references to the version handlers.
                metaBuilder.AddCondition(Ast.Equal(
                                             Methods.GetSelfClassVersionHandle.OpCall(AstUtils.Convert(args.MetaScope.Expression, typeof(RubyScope))),
                                             Ast.Constant(visibilityContext.Class.Version)
                                             ));
            }

            return(method);
        }
コード例 #54
0
 protected override bool Build(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args, bool defaultFallback) {
     Debug.Assert(defaultFallback, "custom fallback not supported");
     ProtocolConversionAction.BuildConversion(metaBuilder, args, _resultType, _conversions);
     return true;
 }
コード例 #55
0
 internal override void ApplyBlockFlowHandling(MetaObjectBuilder metaBuilder, CallArguments args)
 {
     // nop
 }