Exemplo n.º 1
0
        /// <summary>
        /// Resolves an library method overload and builds call expression.
        /// The resulting expression on meta-builder doesn't handle block control flow yet.
        /// </summary>
        internal static void BuildCallNoFlow(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args, string/*!*/ name, 
            IList<MethodBase>/*!*/ overloads, bool includeSelf, bool selfIsInstance) {

            var bindingTarget = ResolveOverload(name, overloads, args, includeSelf, selfIsInstance);
            if (bindingTarget.Success) {
                bool calleeHasBlockParam = HasBlockParameter(bindingTarget.Method);

                // Allocates a variable holding BlockParam. 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.
                //
                // NOTE: We check for null block here -> test fore that fact is added in MakeActualArgs
                if (metaBuilder.BfcVariable == null && args.Signature.HasBlock && args.GetBlock() != null && calleeHasBlockParam) {
                    metaBuilder.BfcVariable = metaBuilder.GetTemporary(typeof(BlockParam), "#bfc");
                }

                var actualArgs = MakeActualArgs(metaBuilder, args, includeSelf, selfIsInstance, calleeHasBlockParam, true);
                var parameterBinder = new RubyParameterBinder(args.RubyContext.Binder, args.MetaContext.Expression, args.Signature.HasScope);
                var targetExpression = bindingTarget.MakeExpression(parameterBinder, actualArgs);

                metaBuilder.Result = targetExpression;
            } else {
                metaBuilder.SetError(
                    Methods.MakeInvalidArgumentTypesError.OpCall(Ast.Constant(name))
                );
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Resolves an library method overload and builds call expression.
        /// The resulting expression on meta-builder doesn't handle block control flow yet.
        /// </summary>
        internal static void BuildCallNoFlow(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args, string/*!*/ name, 
            IList<MethodBase>/*!*/ overloads, SelfCallConvention callConvention) {

            var bindingTarget = ResolveOverload(name, overloads, args, callConvention);
            bool calleeHasBlockParam = bindingTarget.Success && HasBlockParameter(bindingTarget.Method);

            // Allocates a variable holding BlockParam. 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) {
                    if (metaBuilder.BfcVariable == null) {
                        metaBuilder.BfcVariable = metaBuilder.GetTemporary(typeof(BlockParam), "#bfc");
                    }
                    metaBuilder.ControlFlowBuilder = RuleControlFlowBuilder;
                }

                // Block test - we need to test for a block regardless of whether it is actually passed to the method or not
                // since the information that the block is not null is used for overload resolution.
                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)));
                }
            }

            var actualArgs = MakeActualArgs(metaBuilder, args, callConvention, calleeHasBlockParam, true);

            if (bindingTarget.Success) {
                var parameterBinder = new RubyParameterBinder(args.RubyContext.Binder, args.MetaContext.Expression, args.Signature.HasScope);
                metaBuilder.Result = bindingTarget.MakeExpression(parameterBinder, actualArgs);
            } else {
                metaBuilder.SetError(args.RubyContext.RubyBinder.MakeInvalidParametersError(bindingTarget).Expression);
            }
        }