Example #1
0
        private Expression CompileAssignment(
            AssignmentStatementAst assignmentStatementAst,
            MergeRedirectExprs generateRedirectExprs = null)
        {
            var arrayLHS = assignmentStatementAst.Left as ArrayLiteralAst;
            var parenExpressionAst = assignmentStatementAst.Left as ParenExpressionAst;
            if (parenExpressionAst != null)
            {
                arrayLHS = parenExpressionAst.Pipeline.GetPureExpression() as ArrayLiteralAst;
            }

            // If assigning to an array, then we prefer an enumerable result because we use an IList
            // to generate the assignments, no sense in converting to object[], or worse, returning a
            // single object.
            // We should not preserve the partial output if exception is thrown when evaluating right-hand-side expression.
            Expression rightExpr = CaptureStatementResults(assignmentStatementAst.Right,
                arrayLHS != null ? CaptureAstContext.Enumerable : CaptureAstContext.AssignmentWithoutResultPreservation, generateRedirectExprs);

            if (arrayLHS != null)
            {
                rightExpr = DynamicExpression.Dynamic(PSArrayAssignmentRHSBinder.Get(arrayLHS.Elements.Count), typeof(IList), rightExpr);
            }

            var exprs = new List<Expression>
                            {
                            // Set current position in case of errors.
                            UpdatePosition(assignmentStatementAst),
                            ReduceAssignment((ISupportsAssignment)assignmentStatementAst.Left,
                                             assignmentStatementAst.Operator,
                                             rightExpr)
                        };

            return Expression.Block(exprs);
        }
Example #2
0
        private Expression CaptureStatementResultsHelper(
            StatementAst stmt,
            CaptureAstContext context,
            MergeRedirectExprs generateRedirectExprs)
        {
            var commandExpressionAst = stmt as CommandExpressionAst;
            if (commandExpressionAst != null)
            {
                if (commandExpressionAst.Redirections.Count > 0)
                {
                    return GetRedirectedExpression(commandExpressionAst, captureForInput: true);
                }
                return Compile(commandExpressionAst.Expression);
            }

            var assignmentStatementAst = stmt as AssignmentStatementAst;
            if (assignmentStatementAst != null)
            {
                var expr = Compile(assignmentStatementAst);
                if (stmt.Parent is StatementBlockAst)
                {
                    expr = Expression.Block(expr, ExpressionCache.Empty);
                }
                return expr;
            }

            var pipelineAst = stmt as PipelineAst;
            if (pipelineAst != null)
            {
                var expr = pipelineAst.GetPureExpression();
                if (expr != null) { return Compile(expr); }
            }

            return CaptureAstResults(stmt, context, generateRedirectExprs);
        }
Example #3
0
        private Expression CaptureStatementResults(
            StatementAst stmt,
            CaptureAstContext context,
            MergeRedirectExprs generateRedirectExprs = null)
        {
            var result = CaptureStatementResultsHelper(stmt, context, generateRedirectExprs);

            // If we're generating code for a condition and the condition contains some command invocation,
            // we want to be sure that $? is set to true even if the condition fails, e.g.:
            //     if (get-command foo -ea SilentlyContinue) { foo }
            //     $?  # never $false here
            // Many conditions don't invoke commands though, and in trivial empty loops, setting $? = $true
            // does have a measurable impact, so only set $? = $true if the condition might change $? to $false.
            // We do this after evaluating the condition so that you could do something like:
            //    if ((dir file1,file2 -ea SilentlyContinue) -and $?) { <# files both exist, otherwise $? would be $false if 0 or 1 files existed #> }
            if (context == CaptureAstContext.Condition && AstSearcher.FindFirst(stmt, ast => ast is CommandAst, searchNestedScriptBlocks: false) != null)
            {
                var tmp = NewTemp(result.Type, "condTmp");
                result = Expression.Block(new[] { tmp },
                    Expression.Assign(tmp, result),
                    s_setDollarQuestionToTrue,
                    tmp);
            }
            return result;
        }
Example #4
0
        private Expression CaptureAstResults(
            Ast ast,
            CaptureAstContext context,
            MergeRedirectExprs generateRedirectExprs = null)
        {
            Expression result;

            // We'll generate code like:
            //  try {
            //    oldPipe = funcContext.OutputPipe;
            //    resultList = new List<object>();
            //    resultListPipe = new Pipe(resultList);
            //    funcContext.OutputPipe = resultListPipe;
            //    <optionally add merge redirection expressions>
            //    expression...
            //  } finally {
            //    FlushPipe(oldPipe, resultList);
            //    funcContext.OutputPipe = oldPipe;
            //  }

            var temps = new List<ParameterExpression>();
            var exprs = new List<Expression>();
            var catches = new List<CatchBlock>();
            var finallyExprs = new List<Expression>();

            var oldPipe = NewTemp(typeof(Pipe), "oldPipe");
            var resultList = NewTemp(typeof(List<object>), "resultList");
            temps.Add(resultList);
            temps.Add(oldPipe);
            exprs.Add(Expression.Assign(oldPipe, s_getCurrentPipe));
            exprs.Add(Expression.Assign(resultList, Expression.New(CachedReflectionInfo.ObjectList_ctor)));
            exprs.Add(Expression.Assign(s_getCurrentPipe, Expression.New(CachedReflectionInfo.Pipe_ctor, resultList)));
            exprs.Add(Expression.Call(oldPipe, CachedReflectionInfo.Pipe_SetVariableListForTemporaryPipe, s_getCurrentPipe));
            if (generateRedirectExprs != null)
            {
                // Add merge redirection expressions if delegate is provided.
                generateRedirectExprs(exprs, finallyExprs);
            }
            exprs.Add(Compile(ast));

            switch (context)
            {
                case CaptureAstContext.AssignmentWithResultPreservation:
                case CaptureAstContext.AssignmentWithoutResultPreservation:
                    result = Expression.Call(CachedReflectionInfo.PipelineOps_PipelineResult, resultList);

                    // Clear the temporary pipe in case of exception, if we are not required to preserve the results
                    if (context == CaptureAstContext.AssignmentWithoutResultPreservation)
                    {
                        var catchExprs = new List<Expression>
                                         {
                                             Expression.Call(CachedReflectionInfo.PipelineOps_ClearPipe, resultList),
                                             Expression.Rethrow(),
                                             Expression.Constant(null, typeof (object))
                                         };

                        catches.Add(Expression.Catch(typeof(RuntimeException), Expression.Block(typeof(object), catchExprs)));
                    }

                    // PipelineResult might get skipped in some circumstances due to a FlowControlException thrown out, in which case
                    // we write to the oldPipe. This can happen in cases like:
                    //     $(1;2;return 3)
                    finallyExprs.Add(Expression.Call(CachedReflectionInfo.PipelineOps_FlushPipe, oldPipe, resultList));
                    break;
                case CaptureAstContext.Condition:
                    result = DynamicExpression.Dynamic(PSPipelineResultToBoolBinder.Get(), typeof(bool), resultList);
                    break;
                case CaptureAstContext.Enumerable:
                    result = resultList;
                    break;
                default:
                    throw new ArgumentOutOfRangeException("context");
            }

            finallyExprs.Add(Expression.Assign(s_getCurrentPipe, oldPipe));
            exprs.Add(result);

            if (catches.Count > 0)
            {
                return Expression.Block(
                    temps.ToArray(),
                    Expression.TryCatchFinally(Expression.Block(exprs),
                                               Expression.Block(finallyExprs),
                                               catches.ToArray()));
            }

            return Expression.Block(
                    temps.ToArray(),
                    Expression.TryFinally(Expression.Block(exprs),
                                          Expression.Block(finallyExprs)));
        }
Example #5
0
 private Expression CompileAssignment(AssignmentStatementAst assignmentStatementAst, MergeRedirectExprs generateRedirectExprs = null)
 {
     ArrayLiteralAst left = assignmentStatementAst.Left as ArrayLiteralAst;
     if (assignmentStatementAst.Left is ParenExpressionAst)
     {
         left = ((ParenExpressionAst) assignmentStatementAst.Left).Pipeline.GetPureExpression() as ArrayLiteralAst;
     }
     Expression expression = this.CaptureStatementResults(assignmentStatementAst.Right, (left != null) ? CaptureAstContext.Enumerable : CaptureAstContext.Assignment, generateRedirectExprs);
     if (left != null)
     {
         expression = Expression.Dynamic(PSArrayAssignmentRHSBinder.Get(left.Elements.Count), typeof(IList), expression);
     }
     List<Expression> expressions = new List<Expression> {
         this.UpdatePosition(assignmentStatementAst),
         this.ReduceAssignment((ISupportsAssignment) assignmentStatementAst.Left, assignmentStatementAst.Operator, expression)
     };
     return Expression.Block(expressions);
 }
Example #6
0
 private Expression CaptureStatementResultsHelper(StatementAst stmt, CaptureAstContext context, MergeRedirectExprs generateRedirectExprs)
 {
     CommandExpressionAst commandExpr = stmt as CommandExpressionAst;
     if (commandExpr != null)
     {
         if (commandExpr.Redirections.Any<RedirectionAst>())
         {
             return this.GetRedirectedExpression(commandExpr, true);
         }
         return this.Compile(commandExpr.Expression);
     }
     AssignmentStatementAst ast = stmt as AssignmentStatementAst;
     if (ast != null)
     {
         Expression expression = this.Compile(ast);
         if (stmt.Parent is StatementBlockAst)
         {
             expression = Expression.Block(expression, ExpressionCache.Empty);
         }
         return expression;
     }
     PipelineAst ast3 = stmt as PipelineAst;
     if (ast3 != null)
     {
         ExpressionAst pureExpression = ast3.GetPureExpression();
         if (pureExpression != null)
         {
             return this.Compile(pureExpression);
         }
     }
     return this.CaptureAstResults(stmt, context, generateRedirectExprs);
 }
Example #7
0
 private Expression CaptureStatementResults(StatementAst stmt, CaptureAstContext context, MergeRedirectExprs generateRedirectExprs = null)
 {
     Expression right = this.CaptureStatementResultsHelper(stmt, context, generateRedirectExprs);
     if ((context == CaptureAstContext.Condition) && (AstSearcher.FindFirst(stmt, ast => ast is CommandAst, false) != null))
     {
         ParameterExpression left = this.NewTemp(right.Type, "condTmp");
         right = Expression.Block(new ParameterExpression[] { left }, new Expression[] { Expression.Assign(left, right), _setDollarQuestionToTrue, left });
     }
     return right;
 }
Example #8
0
        private Expression CaptureAstResults(Ast ast, CaptureAstContext context, MergeRedirectExprs generateRedirectExprs = null)
        {
            Expression expression;
            List<ParameterExpression> list = new List<ParameterExpression>();
            List<Expression> exprs = new List<Expression>();
            List<Expression> finallyExprs = new List<Expression>();
            ParameterExpression item = this.NewTemp(typeof(Pipe), "oldPipe");
            ParameterExpression expression3 = this.NewTemp(typeof(ArrayList), "arrayList");
            list.Add(expression3);
            list.Add(item);
            exprs.Add(Expression.Assign(item, _getCurrentPipe));
            exprs.Add(Expression.Assign(expression3, Expression.New(CachedReflectionInfo.ArrayList_ctor)));
            exprs.Add(Expression.Assign(_getCurrentPipe, Expression.New(CachedReflectionInfo.Pipe_ctor, new Expression[] { expression3 })));
            if (generateRedirectExprs != null)
            {
                generateRedirectExprs(exprs, finallyExprs);
            }
            exprs.Add(this.Compile(ast));
            switch (context)
            {
                case CaptureAstContext.Assignment:
                    expression = Expression.Call(CachedReflectionInfo.PipelineOps_PipelineResult, expression3);
                    finallyExprs.Add(Expression.Call(CachedReflectionInfo.PipelineOps_FlushPipe, item, expression3));
                    break;

                case CaptureAstContext.Condition:
                    expression = Expression.Dynamic(PSPipelineResultToBoolBinder.Get(), typeof(bool), expression3);
                    break;

                case CaptureAstContext.Enumerable:
                    expression = expression3;
                    break;

                default:
                    throw new ArgumentOutOfRangeException("context");
            }
            finallyExprs.Add(Expression.Assign(_getCurrentPipe, item));
            exprs.Add(expression);
            return Expression.Block(list.ToArray(), new Expression[] { Expression.TryFinally(Expression.Block(exprs), Expression.Block(finallyExprs)) });
        }