public void AddSplatted(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args) { var arg = args.GetSplattedArgument(); var parameter = args.GetSplattedArgumentExpression(); int listLength; ParameterExpression listVariable; if (metaBuilder.AddSplattedArgumentTest(arg, parameter, out listLength, out listVariable)) { if (listLength > 0) { for (int i = 0; i < listLength; i++) { Add( Ast.Call( listVariable, typeof(List <object>).GetMethod("get_Item"), Ast.Constant(i) ) ); } } } else { // argument is not an array => add the argument itself: Add(parameter); } }
/// <summary> /// From control flow perspective it "calls" the proc. /// </summary> internal static void BuildCall( MetaObjectBuilder/*!*/ metaBuilder, Expression/*!*/ procExpression, // proc object Expression/*!*/ selfExpression, // self passed to the proc CallArguments/*!*/ args // user arguments passed to the proc ) { var bfcVariable = metaBuilder.GetTemporary(typeof(BlockParam), "#bfc"); metaBuilder.Result = Ast.Block( Ast.Assign(bfcVariable, Methods.CreateBfcForProcCall.OpCall(AstUtils.Convert(procExpression, typeof(Proc)))), Methods.MethodProcCall.OpCall(bfcVariable, AstFactory.YieldExpression( args.RubyContext, args.GetSimpleArgumentExpressions(), args.GetSplattedArgumentExpression(), args.GetRhsArgumentExpression(), bfcVariable, selfExpression ) ) ); }
public static Expression[]/*!*/ MakeActualArgs(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args, bool includeSelf, bool selfIsInstance, bool calleeHasBlockParam, bool injectMissingBlockParam) { var actualArgs = new List<Expression>(args.ExplicitArgumentCount); // self (instance): if (includeSelf && selfIsInstance) { // test already added by method resolver Debug.Assert(args.TargetExpression != null); AddArgument(actualArgs, args.Target, args.TargetExpression); } Proc block = null; Expression blockExpression = null; // 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 (args.Signature.HasBlock) { block = args.GetBlock(); blockExpression = args.GetBlockExpression(); if (block == null) { metaBuilder.AddRestriction(Ast.Equal(blockExpression, Ast.Constant(null))); } else { // don't need to test the exact type of the Proc since the code is subclass agnostic: metaBuilder.AddRestriction(Ast.NotEqual(blockExpression, Ast.Constant(null))); } } // block: if (calleeHasBlockParam) { if (args.Signature.HasBlock) { if (block == null) { // the user explicitly passed nil as a block arg: actualArgs.Add(Ast.Constant(null)); } else { // pass BlockParam: Debug.Assert(metaBuilder.BfcVariable != null); actualArgs.Add(metaBuilder.BfcVariable); } } else { // no block passed into a method with a BlockParam: actualArgs.Add(Ast.Constant(null)); } } else if (injectMissingBlockParam) { // no block passed into a method w/o a BlockParam (we still need to fill the missing block argument): actualArgs.Add(Ast.Constant(null)); } // self (non-instance): if (includeSelf && !selfIsInstance) { // test already added by method resolver AddArgument(actualArgs, args.Target, args.TargetExpression); } // simple arguments: for (int i = 0; i < args.SimpleArgumentCount; i++) { var value = args.GetSimpleArgument(i); var expr = args.GetSimpleArgumentExpression(i); metaBuilder.AddObjectTypeRestriction(value, expr); AddArgument(actualArgs, value, expr); } // splat argument: int listLength; ParameterExpression listVariable; if (args.Signature.HasSplattedArgument) { object splattedArg = args.GetSplattedArgument(); Expression splattedArgExpression = args.GetSplattedArgumentExpression(); if (metaBuilder.AddSplattedArgumentTest(splattedArg, splattedArgExpression, out listLength, out listVariable)) { // AddTestForListArg only returns 'true' if the argument is a List<object> var list = (List<object>)splattedArg; // get arguments, add tests for (int j = 0; j < listLength; j++) { var value = list[j]; var expr = Ast.Call(listVariable, typeof(List<object>).GetMethod("get_Item"), Ast.Constant(j)); metaBuilder.AddObjectTypeCondition(value, expr); AddArgument(actualArgs, value, expr); } } else { // argument is not an array => add the argument itself: AddArgument(actualArgs, splattedArg, splattedArgExpression); } } // rhs argument: if (args.Signature.HasRhsArgument) { var value = args.GetRhsArgument(); var expr = args.GetRhsArgumentExpression(); metaBuilder.AddObjectTypeRestriction(value, expr); AddArgument(actualArgs, value, expr); } return actualArgs.ToArray(); }
public static Expression[] /*!*/ MakeActualArgs(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args, bool includeSelf, bool selfIsInstance, bool calleeHasBlockParam, bool injectMissingBlockParam) { var actualArgs = new List <Expression>(args.ExplicitArgumentCount); // self (instance): if (includeSelf && selfIsInstance) { // test already added by method resolver Debug.Assert(args.TargetExpression != null); AddArgument(actualArgs, args.Target, args.TargetExpression); } Proc block = null; Expression blockExpression = null; // 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 (args.Signature.HasBlock) { block = args.GetBlock(); blockExpression = args.GetBlockExpression(); if (block == null) { metaBuilder.AddRestriction(Ast.Equal(blockExpression, Ast.Constant(null))); } else { // don't need to test the exact type of the Proc since the code is subclass agnostic: metaBuilder.AddRestriction(Ast.NotEqual(blockExpression, Ast.Constant(null))); } } // block: if (calleeHasBlockParam) { if (args.Signature.HasBlock) { if (block == null) { // the user explicitly passed nil as a block arg: actualArgs.Add(Ast.Constant(null)); } else { // pass BlockParam: Debug.Assert(metaBuilder.BfcVariable != null); actualArgs.Add(metaBuilder.BfcVariable); } } else { // no block passed into a method with a BlockParam: actualArgs.Add(Ast.Constant(null)); } } else if (injectMissingBlockParam) { // no block passed into a method w/o a BlockParam (we still need to fill the missing block argument): actualArgs.Add(Ast.Constant(null)); } // self (non-instance): if (includeSelf && !selfIsInstance) { // test already added by method resolver AddArgument(actualArgs, args.Target, args.TargetExpression); } // simple arguments: for (int i = 0; i < args.SimpleArgumentCount; i++) { var value = args.GetSimpleArgument(i); var expr = args.GetSimpleArgumentExpression(i); metaBuilder.AddObjectTypeRestriction(value, expr); AddArgument(actualArgs, value, expr); } // splat argument: int listLength; ParameterExpression listVariable; if (args.Signature.HasSplattedArgument) { object splattedArg = args.GetSplattedArgument(); Expression splattedArgExpression = args.GetSplattedArgumentExpression(); if (metaBuilder.AddSplattedArgumentTest(splattedArg, splattedArgExpression, out listLength, out listVariable)) { // AddTestForListArg only returns 'true' if the argument is a List<object> var list = (List <object>)splattedArg; // get arguments, add tests for (int j = 0; j < listLength; j++) { var value = list[j]; var expr = Ast.Call(listVariable, typeof(List <object>).GetMethod("get_Item"), Ast.Constant(j)); metaBuilder.AddObjectTypeCondition(value, expr); AddArgument(actualArgs, value, expr); } } else { // argument is not an array => add the argument itself: AddArgument(actualArgs, splattedArg, splattedArgExpression); } } // rhs argument: if (args.Signature.HasRhsArgument) { var value = args.GetRhsArgument(); var expr = args.GetRhsArgumentExpression(); metaBuilder.AddObjectTypeRestriction(value, expr); AddArgument(actualArgs, value, expr); } return(actualArgs.ToArray()); }
/// <summary> /// "yields" to the proc. /// </summary> internal void BuildInvoke(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args) { Assert.NotNull(metaBuilder, args); Debug.Assert(!args.Signature.HasBlock); var convertedTarget = AstUtils.Convert(args.TargetExpression, typeof(BlockParam)); // test for target type: metaBuilder.AddTypeRestriction(args.Target.GetType(), args.TargetExpression); metaBuilder.Result = AstFactory.YieldExpression( args.GetSimpleArgumentExpressions(), args.GetSplattedArgumentExpression(), args.GetRhsArgumentExpression(), convertedTarget, // block param Ast.Property(convertedTarget, SelfProperty) // self ); }
// TODO: OBSOLETE private static Expression[]/*!*/ MakeActualArgs(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args, SelfCallConvention callConvention, bool calleeHasBlockParam, bool injectMissingBlockParam) { var actualArgs = new List<Expression>(); // self (instance): if (callConvention == SelfCallConvention.SelfIsInstance) { // test already added by method resolver Debug.Assert(args.TargetExpression != null); AddArgument(actualArgs, args.Target, args.TargetExpression); } // block: if (calleeHasBlockParam) { if (args.Signature.HasBlock) { if (args.GetBlock() == null) { // the user explicitly passed nil as a block arg: actualArgs.Add(AstUtils.Constant(null)); } else { // pass BlockParam: Debug.Assert(metaBuilder.BfcVariable != null); actualArgs.Add(metaBuilder.BfcVariable); } } else { // no block passed into a method with a BlockParam: actualArgs.Add(AstUtils.Constant(null)); } } else if (injectMissingBlockParam) { // no block passed into a method w/o a BlockParam (we still need to fill the missing block argument): actualArgs.Add(AstUtils.Constant(null)); } // self (non-instance): if (callConvention == SelfCallConvention.SelfIsParameter) { // test already added by method resolver AddArgument(actualArgs, args.Target, args.TargetExpression); } // simple arguments: for (int i = 0; i < args.SimpleArgumentCount; i++) { var value = args.GetSimpleArgument(i); var expr = args.GetSimpleArgumentExpression(i); // TODO: overload-resolution restrictions metaBuilder.AddObjectTypeRestriction(value, expr); AddArgument(actualArgs, value, expr); } // splat argument: int listLength; ParameterExpression listVariable; if (args.Signature.HasSplattedArgument) { object splattedArg = args.GetSplattedArgument(); Expression splattedArgExpression = args.GetSplattedArgumentExpression(); if (metaBuilder.AddSplattedArgumentTest(splattedArg, splattedArgExpression, out listLength, out listVariable)) { // AddTestForListArg only returns 'true' if the argument is a List<object> var list = (List<object>)splattedArg; // get arguments, add tests for (int j = 0; j < listLength; j++) { var value = list[j]; var expr = Ast.Call(listVariable, typeof(List<object>).GetMethod("get_Item"), AstUtils.Constant(j)); // TODO: overload-resolution restrictions metaBuilder.AddObjectTypeCondition(value, expr); AddArgument(actualArgs, value, expr); } } else { // argument is not an array => add the argument itself: AddArgument(actualArgs, splattedArg, splattedArgExpression); } } // rhs argument: if (args.Signature.HasRhsArgument) { var value = args.GetRhsArgument(); var expr = args.GetRhsArgumentExpression(); // TODO: overload-resolution restrictions metaBuilder.AddObjectTypeRestriction(value, expr); AddArgument(actualArgs, value, expr); } return actualArgs.ToArray(); }
/// <summary> /// From control flow perspective it "calls" the proc. /// </summary> internal static void BuildCall( MetaObjectBuilder/*!*/ metaBuilder, Expression/*!*/ procExpression, // proc object Expression/*!*/ selfExpression, // self passed to the proc Expression callingMethodExpression, // RubyLambdaMethodInfo passed to the proc via BlockParam CallArguments/*!*/ args // user arguments passed to the proc ) { var bfcVariable = metaBuilder.GetTemporary(typeof(BlockParam), "#bfc"); var resultVariable = metaBuilder.GetTemporary(typeof(object), "#result"); metaBuilder.Result = AstFactory.Block( Ast.Assign(bfcVariable, (callingMethodExpression != null) ? Methods.CreateBfcForMethodProcCall.OpCall( AstUtils.Convert(procExpression, typeof(Proc)), callingMethodExpression ) : Methods.CreateBfcForProcCall.OpCall( AstUtils.Convert(procExpression, typeof(Proc)) ) ), Ast.Assign(resultVariable, AstFactory.YieldExpression( args.GetSimpleArgumentExpressions(), args.GetSplattedArgumentExpression(), args.GetRhsArgumentExpression(), bfcVariable, selfExpression )), Methods.MethodProcCall.OpCall(bfcVariable, resultVariable), resultVariable ); }