TransformWrite() private method

private TransformWrite ( AstGenerator gen, System.Linq.Expressions rightValue ) : Expression
gen AstGenerator
rightValue System.Linq.Expressions
return System.Linq.Expressions.Expression
        internal override MSA.Expression /*!*/ TransformRead(AstGenerator /*!*/ gen)
        {
            // TODO:
            // {target}[{arguments}] op= rhs
            // we need to evaluate {arguments} once: http://ironruby.codeplex.com/workitem/4525

            // first, read target into a temp:
            MSA.Expression transformedLeftTarget = _left.TransformTargetRead(gen);
            MSA.Expression leftTargetTemp;

            if (transformedLeftTarget != null)
            {
                leftTargetTemp = gen.CurrentScope.DefineHiddenVariable(String.Empty, transformedLeftTarget.Type);
            }
            else
            {
                leftTargetTemp = null;
            }

            MSA.Expression transformedRight = _right.TransformRead(gen);

            // lhs &&= rhs  -->  lhs && (lhs = rhs)
            // lhs ||= rhs  -->  lhs || (lhs = rhs)
            if (Operation == Symbols.And || Operation == Symbols.Or)
            {
                MSA.Expression transformedLeftRead = _left.TransformRead(gen,
                                                                         (transformedLeftTarget != null) ? Ast.Assign(leftTargetTemp, transformedLeftTarget) : null,
                                                                         true // tryRead
                                                                         );

                MSA.Expression transformedWrite = _left.TransformWrite(gen, leftTargetTemp, transformedRight);

                if (Operation == Symbols.And)
                {
                    return(AndExpression.TransformRead(gen, transformedLeftRead, transformedWrite));
                }
                else
                {
                    return(OrExpression.TransformRead(gen, transformedLeftRead, transformedWrite));
                }
            }
            else
            {
                // lhs op= rhs  -->  lhs = lhs op rhs
                if (Operation != null)
                {
                    MSA.Expression transformedLeftRead = _left.TransformRead(gen, leftTargetTemp, false);
                    transformedRight = MethodCall.TransformRead(this, gen, false, Operation, transformedLeftRead, null, null, transformedRight, null);
                }

                // transform lhs write assigning lhs-target temp:
                return(_left.TransformWrite(gen,
                                            (transformedLeftTarget != null) ? Ast.Assign(leftTargetTemp, transformedLeftTarget) : null,
                                            transformedRight
                                            ));
            }
        }
Example #2
0
        //
        // rescue stmts                     ... if (StandardError === $!) { stmts; }
        // rescue <types> stmts             ... temp1 = type1; ...; if (<temp1> === $! || ...) { stmts; }
        // rescue <types> => <lvalue> stmts ... temp1 = type1; ...; if (<temp1> === $! || ...) { <lvalue> = $!; stmts; }
        //
        internal IfStatementTest /*!*/ Transform(AstGenerator /*!*/ gen, ResultOperation resultOperation)
        {
            Assert.NotNull(gen);

            MSA.Expression condition;
            if (_types.Length != 0)
            {
                var comparisonSiteStorage = Ast.Constant(new BinaryOpStorage(gen.Context));

                if (_types.Length == 1)
                {
                    condition = MakeCompareException(gen, comparisonSiteStorage, _types[0].TransformRead(gen), _types[0] is SplattedArgument);
                }
                else
                {
                    // forall{i}: <temps[i]> = evaluate type[i]
                    var temps = new MSA.Expression[_types.Length];
                    var exprs = new BlockBuilder();

                    for (int i = 0; i < _types.Length; i++)
                    {
                        var t   = _types[i].TransformRead(gen);
                        var tmp = gen.CurrentScope.DefineHiddenVariable("#type_" + i, t.Type);
                        temps[i] = tmp;
                        exprs.Add(Ast.Assign(tmp, t));
                    }

                    // CompareException(<temps[0]>) || ... CompareException(<temps[n]>) || CompareSplattedExceptions(<splatTypes>)
                    condition = MakeCompareException(gen, comparisonSiteStorage, temps[0], _types[0] is SplattedArgument);
                    for (int i = 1; i < _types.Length; i++)
                    {
                        condition = Ast.OrElse(condition, MakeCompareException(gen, comparisonSiteStorage, temps[i], _types[i] is SplattedArgument));
                    }

                    // (temps[0] = type[0], ..., temps[n] == type[n], condition)
                    exprs.Add(condition);
                    condition = exprs;
                }
            }
            else
            {
                condition = Methods.CompareDefaultException.OpCall(gen.CurrentScopeVariable);
            }

            return(AstUtils.IfCondition(condition,
                                        gen.TransformStatements(
                                            // <lvalue> = e;
                                            (_target != null) ? _target.TransformWrite(gen, Methods.GetCurrentException.OpCall(gen.CurrentScopeVariable)) : null,

                                            // body:
                                            _statements,

                                            resultOperation
                                            )
                                        ));
        }
Example #3
0
        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);
        }
Example #4
0
        //
        // rescue stmts                     ... if (StandardError === $!) { stmts; }
        // rescue <types> stmts             ... temp1 = type1; ...; if (<temp1> === $! || ...) { stmts; }
        // rescue <types> => <lvalue> stmts ... temp1 = type1; ...; if (<temp1> === $! || ...) { <lvalue> = $!; stmts; }
        //
        internal IfStatementTest /*!*/ Transform(AstGenerator /*!*/ gen, ResultOperation resultOperation)
        {
            Assert.NotNull(gen);

            MSA.Expression condition;
            if (_types.Count != 0 || _splatType != null)
            {
                if (_types.Count == 0)
                {
                    // splat only:
                    condition = MakeCompareSplattedExceptions(gen, TransformSplatType(gen));
                }
                else if (_types.Count == 1 && _splatType == null)
                {
                    condition = MakeCompareException(gen, _types[0].TransformRead(gen));
                }
                else
                {
                    // forall{i}: <temps[i]> = evaluate type[i]
                    var temps = new MSA.Expression[_types.Count + (_splatType != null ? 1 : 0)];
                    var exprs = new MSA.Expression[temps.Length + 1];

                    int i = 0;
                    while (i < _types.Count)
                    {
                        var tmp = gen.CurrentScope.DefineHiddenVariable("#type_" + i, typeof(object));
                        temps[i] = tmp;
                        exprs[i] = Ast.Assign(tmp, _types[i].TransformRead(gen));
                        i++;
                    }

                    if (_splatType != null)
                    {
                        var tmp = gen.CurrentScope.DefineHiddenVariable("#type_" + i, typeof(object));
                        temps[i] = tmp;
                        exprs[i] = Ast.Assign(tmp, TransformSplatType(gen));

                        i++;
                    }

                    Debug.Assert(i == temps.Length);

                    // CompareException(<temps[0]>) || ... CompareException(<temps[n]>) || CompareSplattedExceptions(<splatTypes>)
                    i         = 0;
                    condition = MakeCompareException(gen, temps[i++]);
                    while (i < _types.Count)
                    {
                        condition = Ast.OrElse(condition, MakeCompareException(gen, temps[i++]));
                    }

                    if (_splatType != null)
                    {
                        condition = Ast.OrElse(condition, MakeCompareSplattedExceptions(gen, temps[i++]));
                    }

                    Debug.Assert(i == temps.Length);

                    // (temps[0] = type[0], ..., temps[n] == type[n], condition)
                    exprs[exprs.Length - 1] = condition;
                    condition = AstFactory.Block(exprs);
                }
            }
            else
            {
                condition = Methods.CompareDefaultException.OpCall(gen.CurrentScopeVariable, gen.CurrentSelfVariable);
            }

            return(AstUtils.IfCondition(condition,
                                        gen.TransformStatements(
                                            // <lvalue> = e;
                                            (_target != null) ? _target.TransformWrite(gen, Methods.GetCurrentException.OpCall(gen.CurrentScopeVariable)) : null,

                                            // body:
                                            _statements,

                                            resultOperation
                                            )
                                        ));
        }