Exemple #1
0
        internal static MSA.Expression /*!*/ YieldExpression(
            RubyContext /*!*/ context,
            AstExpressions /*!*/ arguments,
            MSA.Expression splattedArgument,
            MSA.Expression rhsArgument,
            MSA.Expression /*!*/ bfcVariable,
            MSA.Expression /*!*/ selfArgument)
        {
            Assert.NotNull(arguments, bfcVariable, selfArgument);

            bool hasArgumentArray;
            var  opMethod = Methods.Yield(arguments.Count, splattedArgument != null, rhsArgument != null, out hasArgumentArray);

            var args = new AstExpressions();

            foreach (var arg in arguments)
            {
                args.Add(AstUtils.Box(arg));
            }

            if (hasArgumentArray)
            {
                args = new AstExpressions {
                    Ast.NewArrayInit(typeof(object), args)
                };
            }

            if (splattedArgument != null)
            {
                args.Add(AstUtils.LightDynamic(SplatAction.Make(context), typeof(IList), splattedArgument));
            }

            if (rhsArgument != null)
            {
                args.Add(AstUtils.Box(rhsArgument));
            }

            args.Add(AstUtils.Box(selfArgument));
            args.Add(bfcVariable);

            return(Ast.Call(opMethod, args));
        }
Exemple #2
0
        internal void TransformToCall(AstGenerator /*!*/ gen, CallSiteBuilder /*!*/ siteBuilder)
        {
            if (_expressions != null)
            {
                foreach (var arg in _expressions)
                {
                    siteBuilder.Add(arg.TransformRead(gen));
                }
            }

            if (_maplets != null)
            {
                siteBuilder.Add(gen.TransformToHashConstructor(_maplets));
            }

            if (_array != null)
            {
                siteBuilder.SplattedArgument =
                    AstUtils.LightDynamic(SplatAction.Make(gen.Context), typeof(IList), _array.TransformRead(gen));
            }
        }
Exemple #3
0
        internal static MSA.Expression /*!*/ TransformRead(AstGenerator /*!*/ gen, AstExpressions /*!*/ rightValues,
                                                           MSA.Expression splattedValue, bool doSplat)
        {
            Assert.NotNull(gen, rightValues);

            MSA.Expression result;

            // We need to distinguish various special cases here.
            // For parallel assignment specification, see "Ruby Language.docx/Runtime/Parallel Assignment".

            // R(0,*)?
            bool rightNoneSplat = rightValues.Count == 0 && splattedValue != null;

            // R(1,-)?
            bool rightOneNone = rightValues.Count == 1 && splattedValue == null;

            if (rightNoneSplat)
            {
                result = AstUtils.LightDynamic(SplatAction.Make(gen.Context), typeof(IList), splattedValue);
                if (doSplat)
                {
                    result = Methods.Splat.OpCall(result);
                }
            }
            else if (rightOneNone && doSplat)
            {
                result = rightValues[0];
            }
            else
            {
                result = Methods.MakeArrayOpCall(rightValues);

                if (splattedValue != null)
                {
                    result = Methods.SplatAppend.OpCall(result, AstUtils.LightDynamic(SplatAction.Make(gen.Context), typeof(IList), splattedValue));
                }
            }
            return(result);
        }
        private MSA.Expression /*!*/ TransformWrite(AstGenerator /*!*/ gen, AstExpressions /*!*/ rightValues, MSA.Expression splattedValue)
        {
            // We need to distinguish various special cases here.
            // Each of the bool variables defined below is true iff the corresponding special form of LHS/RHS occurs.
            // These flags drive the DLR AST being produced by this method.
            // For parallel assignment specification, see "Ruby Language.docx/Runtime/Parallel Assignment".

            // L(0,-) not applicable
            Debug.Assert(!(_leftValues.Count == 0 && _unsplattedValue == null));

            // L(1,-)?
            bool leftOneNone = _leftValues.Count == 1 && _unsplattedValue == null;

            // L(0,*)?
            bool leftNoneSplat = _leftValues.Count == 0 && _unsplattedValue != null;

            // R(0,*)?
            bool rightNoneSplat = rightValues.Count == 0 && splattedValue != null;

            // R(1,-)?
            bool rightOneNone = rightValues.Count == 1 && splattedValue == null;

            // R(1,*)?
            bool rightOneSplat = rightValues.Count == 1 && splattedValue != null;

            // R(0,-) not applicable
            Debug.Assert(!(rightValues.Count == 0 && splattedValue == null));

            MSA.Expression resultExpression;

            if (leftOneNone)
            {
                // L(1,-):

                // recurse right away (X) = RHS is equivalent to X = RHS:
                CompoundLeftValue compound = _leftValues[0] as CompoundLeftValue;
                if (compound != null)
                {
                    return(compound.TransformWrite(gen, rightValues, splattedValue));
                }

                if (rightOneSplat)
                {
                    // R(1,*)
                    resultExpression = Methods.SplatPair.OpCall(
                        AstUtils.Box(rightValues[0]),
                        AstUtils.LightDynamic(SplatAction.Make(gen.Context), typeof(IList), splattedValue)
                        );
                }
                else
                {
                    // case 1: R(1,-)
                    // case 2: R(0,*)
                    // case 3: otherwise
                    resultExpression = Arguments.TransformRead(gen, rightValues, splattedValue, true /* Splat */);
                }

                return(_leftValues[0].TransformWrite(gen, resultExpression));
            }

            bool optimizeReads = true;

            if (rightOneNone && !leftNoneSplat)
            {
                // R(1,-) && !L(0,*)
                resultExpression = Methods.Unsplat.OpCall(
                    AstUtils.LightDynamic(ConvertToArraySplatAction.Make(gen.Context), rightValues[0])
                    );
                optimizeReads = false;
            }
            else
            {
                // case 1: R(0,*) = L
                // case 2: otherwise
                resultExpression = Arguments.TransformRead(gen, rightValues, splattedValue, false /* Unsplat */);
                optimizeReads    = !rightNoneSplat;
            }

            var writes = new AstBlock();

            MSA.Expression result = gen.CurrentScope.DefineHiddenVariable("#rhs", typeof(IList));
            writes.Add(Ast.Assign(result, resultExpression));

            MethodInfo itemGetter = Methods.IList_get_Item;

            for (int i = 0; i < _leftValues.Count; i++)
            {
                MSA.Expression rvalue;

                if (optimizeReads)
                {
                    if (i < rightValues.Count)
                    {
                        // unchecked get item:
                        rvalue = Ast.Call(result, itemGetter, AstUtils.Constant(i));
                    }
                    else if (splattedValue != null)
                    {
                        // checked get item:
                        rvalue = Methods.GetArrayItem.OpCall(result, AstUtils.Constant(i));
                    }
                    else
                    {
                        // missing item:
                        rvalue = AstUtils.Constant(null);
                    }
                }
                else
                {
                    rvalue = Methods.GetArrayItem.OpCall(result, AstUtils.Constant(i));
                }

                writes.Add(_leftValues[i].TransformWrite(gen, rvalue));
            }

            // unsplatting the rest of rhs values into an array:
            if (_unsplattedValue != null)
            {
                // copies the rest of resulting array to the *LHS;
                // the resulting array contains splatted *RHS - no need for additional appending:
                MSA.Expression array = Methods.GetArraySuffix.OpCall(result, AstUtils.Constant(_leftValues.Count));

                // assign the array (possibly empty) to *LHS:
                writes.Add(_unsplattedValue.TransformWrite(gen, array));
            }

            writes.Add(result);
            return(writes);
        }
Exemple #5
0
 private MSA.Expression /*!*/ TransformSplatType(AstGenerator /*!*/ gen)
 {
     return(AstUtils.LightDynamic(SplatAction.Make(gen.Context), typeof(IList), _splatType.TransformRead(gen)));
 }