示例#1
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, 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();
            }
        }
示例#2
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();
            }
        }