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++; } }
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, AstUtils.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 AstUtils.Constant(null); }); if (HasParamsArray) { actualArgs.AddParamsArray(); } }
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(); } }