private AddSplattedArgumentTest ( IList value, Expression expression, int &listLength, System.Linq.Expressions.ParameterExpression &listVariable ) : void | ||
value | IList | |
expression | Expression | |
listLength | int | |
listVariable | System.Linq.Expressions.ParameterExpression | |
return | void |
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); } }
public void AddSplatted(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args) { var arg = args.GetSplattedMetaArgument(); int listLength; ParameterExpression listVariable; metaBuilder.AddSplattedArgumentTest((IList)arg.Value, arg.Expression, out listLength, out listVariable); if (listLength > 0) { for (int i = 0; i < listLength; i++) { Add( Ast.Call( listVariable, typeof(IList).GetMethod("get_Item"), AstUtils.Constant(i) ) ); } } }
private static ActualArguments /*!*/ CreateActualArguments(List <DynamicMetaObject> /*!*/ normalized, MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args, int hidden, int preSplatLimit, int postSplatLimit, out int lastSplattedArg, out IList list, out ParameterExpression listVariable) { int firstSplattedArg, splatIndex, collapsedArgCount; // simple arguments: for (int i = 0; i < args.SimpleArgumentCount; i++) { normalized.Add(args.GetSimpleMetaArgument(i)); } // splat argument: list = null; listVariable = null; if (args.Signature.HasSplattedArgument) { firstSplattedArg = normalized.Count; int listLength; var splatted = args.GetSplattedMetaArgument(); list = (IList)splatted.Value; metaBuilder.AddSplattedArgumentTest(list, splatted.Expression, out listLength, out listVariable); int i = 0; while (i < Math.Min(listLength, preSplatLimit - firstSplattedArg)) { normalized.Add(MakeSplattedItem(list, listVariable, i)); i++; } // skip items that are not needed for overload resolution splatIndex = normalized.Count; i = Math.Max(i, listLength - (postSplatLimit - (args.Signature.HasRhsArgument ? 1 : 0))); while (i < listLength) { normalized.Add(MakeSplattedItem(list, listVariable, i)); i++; } collapsedArgCount = listLength - (normalized.Count - firstSplattedArg); lastSplattedArg = normalized.Count - 1; } else { splatIndex = firstSplattedArg = lastSplattedArg = -1; collapsedArgCount = 0; } Debug.Assert(collapsedArgCount >= 0); // rhs argument: if (args.Signature.HasRhsArgument) { normalized.Add(args.GetRhsMetaArgument()); } return(new ActualArguments( normalized.ToArray(), DynamicMetaObject.EmptyMetaObjects, ArrayUtils.EmptyStrings, hidden, collapsedArgCount, firstSplattedArg, splatIndex )); }
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()); }
public void AddSplatted(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args) { var arg = args.GetSplattedMetaArgument(); int listLength; ParameterExpression listVariable; metaBuilder.AddSplattedArgumentTest((IList)arg.Value, arg.Expression, out listLength, out listVariable); if (listLength > 0) { for (int i = 0; i < listLength; i++) { Add( Ast.Call( listVariable, typeof(IList).GetMethod("get_Item"), AstUtils.Constant(i) ) ); } } }
private static ActualArguments/*!*/ CreateActualArguments(List<DynamicMetaObject>/*!*/ normalized, MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args, int hidden, int preSplatLimit, int postSplatLimit, out int lastSplattedArg, out IList list, out ParameterExpression listVariable) { int firstSplattedArg, splatIndex, collapsedArgCount; // simple arguments: for (int i = 0; i < args.SimpleArgumentCount; i++) { normalized.Add(args.GetSimpleMetaArgument(i)); } // splat argument: list = null; listVariable = null; if (args.Signature.HasSplattedArgument) { firstSplattedArg = normalized.Count; int listLength; var splatted = args.GetSplattedMetaArgument(); list = (IList)splatted.Value; metaBuilder.AddSplattedArgumentTest(list, splatted.Expression, out listLength, out listVariable); int i = 0; while (i < Math.Min(listLength, preSplatLimit - firstSplattedArg)) { normalized.Add(MakeSplattedItem(list, listVariable, i)); i++; } // skip items that are not needed for overload resolution splatIndex = normalized.Count; i = Math.Max(i, listLength - (postSplatLimit - (args.Signature.HasRhsArgument ? 1 : 0))); while (i < listLength) { normalized.Add(MakeSplattedItem(list, listVariable, i)); i++; } collapsedArgCount = listLength - (normalized.Count - firstSplattedArg); lastSplattedArg = normalized.Count - 1; } else { splatIndex = firstSplattedArg = lastSplattedArg = -1; collapsedArgCount = 0; } Debug.Assert(collapsedArgCount >= 0); // rhs argument: if (args.Signature.HasRhsArgument) { normalized.Add(args.GetRhsMetaArgument()); } return new ActualArguments( normalized.ToArray(), DynamicMetaObject.EmptyMetaObjects, ArrayUtils.EmptyStrings, hidden, collapsedArgCount, firstSplattedArg, splatIndex ); }
// 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(); }
// Normalizes arguments: inserts self, expands splats, and inserts rhs arg. // Adds any restrictions/conditions applied to the arguments to the given meta-builder. internal static DynamicMetaObject[]/*!*/ NormalizeArguments(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args, SelfCallConvention callConvention, bool calleeHasBlockParam, bool injectMissingBlockParam) { var result = new List<DynamicMetaObject>(); // self (instance): if (callConvention == SelfCallConvention.SelfIsInstance) { result.Add(args.MetaTarget); } // block: if (calleeHasBlockParam) { if (args.Signature.HasBlock) { if (args.GetMetaBlock() == null) { // the user explicitly passed nil as a block arg: result.Add(RubyBinder.NullMetaObject); } else { // pass BlockParam: Debug.Assert(metaBuilder.BfcVariable != null); result.Add(new DynamicMetaObject(metaBuilder.BfcVariable, BindingRestrictions.Empty)); } } else { // no block passed into a method with a BlockParam: result.Add(RubyBinder.NullMetaObject); } } else if (injectMissingBlockParam) { // no block passed into a method w/o a BlockParam (we still need to fill the missing block argument): result.Add(RubyBinder.NullMetaObject); } // self (parameter): if (callConvention == SelfCallConvention.SelfIsParameter) { result.Add(args.MetaTarget); } // simple arguments: for (int i = 0; i < args.SimpleArgumentCount; i++) { result.Add(args.GetSimpleMetaArgument(i)); } // splat argument: int listLength; ParameterExpression listVariable; if (args.Signature.HasSplattedArgument) { var splatted = args.GetSplattedMetaArgument(); if (metaBuilder.AddSplattedArgumentTest(splatted.Value, splatted.Expression, out listLength, out listVariable)) { // AddTestForListArg only returns 'true' if the argument is a List<object> var list = (List<object>)splatted.Value; // get arguments, add tests for (int j = 0; j < listLength; j++) { result.Add(DynamicMetaObject.Create( list[j], Ast.Call(listVariable, typeof(List<object>).GetMethod("get_Item"), AstUtils.Constant(j)) )); } } else { // argument is not an array => add the argument itself: result.Add(splatted); } } // rhs argument: if (args.Signature.HasRhsArgument) { result.Add(args.GetRhsMetaArgument()); } return result.ToArray(); }
public void AddSplatted(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args) { var arg = args.GetSplattedMetaArgument(); int listLength; ParameterExpression listVariable; if (metaBuilder.AddSplattedArgumentTest(arg.Value, arg.Expression, out listLength, out listVariable)) { if (listLength > 0) { for (int i = 0; i < listLength; i++) { Add( Ast.Call( listVariable, typeof(List<object>).GetMethod("get_Item"), AstUtils.Constant(i) ) ); } } } else { // argument is not an array => add the argument itself: Add(arg.Expression); } }
public void AddCallArguments(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args) { _callArguments = args; // calculate actual argument count: _actualArgumentCount = args.SimpleArgumentCount; if (args.Signature.HasSplattedArgument) { var splattedArg = args.GetSplattedMetaArgument(); metaBuilder.AddSplattedArgumentTest((IList)splattedArg.Value, splattedArg.Expression, out _listLength, out _listVariable); _actualArgumentCount += _listLength; } if (args.Signature.HasRhsArgument) { _actualArgumentCount++; } // check: if (HasTooFewArguments) { metaBuilder.SetWrongNumberOfArgumentsError(_actualArgumentCount, _mandatoryParamCount); return; } if (HasTooManyArguments) { metaBuilder.SetWrongNumberOfArgumentsError(_actualArgumentCount, _mandatoryParamCount); return; } bool isSplatted; // leading mandatory: for (int i = 0; i < _leadingMandatoryParamCount; i++) { _arguments[LeadingMandatoryIndex + i] = GetArgument(i, out isSplatted); } // trailing mandatory: for (int i = 0; i < TrailingMandatoryCount; i++) { _arguments[TrailingMandatoryIndex + i] = GetArgument(_actualArgumentCount - TrailingMandatoryCount + i, out isSplatted); } int start = _leadingMandatoryParamCount; int end = _actualArgumentCount - TrailingMandatoryCount; // optional: for (int i = 0; i < _optionalParamCount; i++) { _arguments[OptionalParameterIndex + i] = (start < end) ? GetArgument(start++, out isSplatted) : Ast.Field(null, Fields.DefaultArgument); } // unsplat: if (_hasUnsplatParameter) { Expression array; if (args.Signature.HasSplattedArgument) { // simple: var argsToUnsplat = new List <Expression>(); while (start < end) { var arg = GetArgument(start, out isSplatted); if (isSplatted) { break; } argsToUnsplat.Add(AstUtils.Box(arg)); start++; } array = Methods.MakeArrayOpCall(argsToUnsplat); int rangeStart = start - args.SimpleArgumentCount; int rangeLength = Math.Min(end - start, _listLength - rangeStart); // splatted: if (rangeLength > 0) { array = Methods.AddSubRange.OpCall(array, _listVariable, Ast.Constant(rangeStart), Ast.Constant(rangeLength)); start += rangeLength; } // rhs: while (start < end) { array = Methods.AddItem.OpCall(array, AstUtils.Box(GetArgument(start, out isSplatted))); start++; } } else { var argsToUnsplat = new List <Expression>(end - start); while (start < end) { argsToUnsplat.Add(AstUtils.Box(GetArgument(start++, out isSplatted))); } array = Methods.MakeArrayOpCall(argsToUnsplat); } _arguments[UnsplatParameterIndex] = array; } _callArguments = null; _listVariable = null; Debug.Assert(CollectionUtils.TrueForAll(_arguments, (e) => e != null)); }
public void AddCallArguments(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args) { _callArguments = args; // calculate actual argument count: _actualArgumentCount = args.SimpleArgumentCount; if (args.Signature.HasSplattedArgument) { var splattedArg = args.GetSplattedMetaArgument(); metaBuilder.AddSplattedArgumentTest((IList)splattedArg.Value, splattedArg.Expression, out _listLength, out _listVariable); _actualArgumentCount += _listLength; } if (args.Signature.HasRhsArgument) { _actualArgumentCount++; } // check: if (HasTooFewArguments) { metaBuilder.SetWrongNumberOfArgumentsError(_actualArgumentCount, _mandatoryParamCount); return; } if (HasTooManyArguments) { metaBuilder.SetWrongNumberOfArgumentsError(_actualArgumentCount, _mandatoryParamCount); return; } bool isSplatted; // leading mandatory: for (int i = 0; i < _leadingMandatoryParamCount; i++) { _arguments[LeadingMandatoryIndex + i] = GetArgument(i, out isSplatted); } // trailing mandatory: for (int i = 0; i < TrailingMandatoryCount; i++) { _arguments[TrailingMandatoryIndex + i] = GetArgument(_actualArgumentCount - TrailingMandatoryCount + i, out isSplatted); } int start = _leadingMandatoryParamCount; int end = _actualArgumentCount - TrailingMandatoryCount; // optional: for (int i = 0; i < _optionalParamCount; i++) { _arguments[OptionalParameterIndex + i] = (start < end) ? GetArgument(start++, out isSplatted) : Ast.Field(null, Fields.DefaultArgument); } // unsplat: if (_hasUnsplatParameter) { Expression array; if (args.Signature.HasSplattedArgument) { // simple: var argsToUnsplat = new List<Expression>(); while (start < end) { var arg = GetArgument(start, out isSplatted); if (isSplatted) { break; } argsToUnsplat.Add(AstUtils.Box(arg)); start++; } array = Methods.MakeArrayOpCall(argsToUnsplat); int rangeStart = start - args.SimpleArgumentCount; int rangeLength = Math.Min(end - start, _listLength - rangeStart); // splatted: if (rangeLength > 0) { array = Methods.AddSubRange.OpCall(array, _listVariable, Ast.Constant(rangeStart), Ast.Constant(rangeLength)); start += rangeLength; } // rhs: while (start < end) { array = Methods.AddItem.OpCall(array, AstUtils.Box(GetArgument(start, out isSplatted))); start++; } } else { var argsToUnsplat = new List<Expression>(end - start); while (start < end) { argsToUnsplat.Add(AstUtils.Box(GetArgument(start++, out isSplatted))); } array = Methods.MakeArrayOpCall(argsToUnsplat); } _arguments[UnsplatParameterIndex] = array; } _callArguments = null; _listVariable = null; Debug.Assert(CollectionUtils.TrueForAll(_arguments, (e) => e != null)); }