public override MSAst.Expression Reduce()
        {
            MSAst.Expression raiseExpression;
            if (_type == null && _value == null && _traceback == null)
            {
                raiseExpression = Ast.Call(
                    AstMethods.MakeRethrownException,
                    Parent.LocalContext
                    );

                if (!InFinally)
                {
                    raiseExpression = Ast.Block(
                        UpdateLineUpdated(true),
                        raiseExpression
                        );
                }
            }
            else
            {
                raiseExpression = Ast.Call(
                    AstMethods.MakeException,
                    Parent.LocalContext,
                    TransformOrConstantNull(_type, typeof(object)),
                    TransformOrConstantNull(_value, typeof(object)),
                    TransformOrConstantNull(_traceback, typeof(object))
                    );
            }

            return(GlobalParent.AddDebugInfo(
                       Ast.Throw(raiseExpression),
                       Span
                       ));
        }
        public override MSAst.Expression Reduce()
        {
            MSAst.MethodCallExpression call;

            if (_locals == null && _globals == null)
            {
                // exec code
                call = Ast.Call(
                    AstMethods.UnqualifiedExec,
                    Parent.LocalContext,
                    AstUtils.Convert(_code, typeof(object))
                    );
            }
            else
            {
                // exec code in globals [ , locals ]
                // We must have globals now (locals is last and may be absent)
                Debug.Assert(_globals != null);
                call = Ast.Call(
                    AstMethods.QualifiedExec,
                    Parent.LocalContext,
                    AstUtils.Convert(_code, typeof(object)),
                    TransformAndDynamicConvert(_globals, typeof(PythonDictionary)),
                    TransformOrConstantNull(_locals, typeof(object))
                    );
            }

            return(GlobalParent.AddDebugInfo(call, Span));
        }
Exemple #3
0
        public override MSAst.Expression Reduce()
        {
            if (Parent.IsGeneratorMethod)
            {
                if (_expression != null)
                {
                    // Statements can't return null, so return a rethrow.
                    // Callers should detecet the ag.AddError and avoid trying to execute the tree,
                    // but if they accidentally do, use Throw instead of empty so that
                    // we'll get an exception.
                    return(Ast.Throw(
                               Ast.New(
                                   typeof(InvalidOperationException).GetConstructor(Type.EmptyTypes)
                                   )
                               ));
                }

                return(GlobalParent.AddDebugInfo(AstUtils.YieldBreak(GeneratorLabel), Span));
            }

            return(GlobalParent.AddDebugInfo(
                       Ast.Return(
                           FunctionDefinition._returnLabel,
                           TransformOrConstantNull(_expression, typeof(object))
                           ),
                       Span
                       ));
        }
Exemple #4
0
        public override MSAst.Expression Reduce()
        {
            ReadOnlyCollectionBuilder <MSAst.Expression> statements = new ReadOnlyCollectionBuilder <MSAst.Expression>();

            for (int i = 0; i < _names.Length; i++)
            {
                statements.Add(
                    // _references[i] = PythonOps.Import(<code context>, _names[i])
                    GlobalParent.AddDebugInfoAndVoid(
                        AssignValue(
                            Parent.GetVariableExpression(_variables[i]),
                            LightExceptions.CheckAndThrow(
                                Expression.Call(
                                    _asNames[i] == null ? AstMethods.ImportTop : AstMethods.ImportBottom,
                                    Parent.LocalContext,                                     // 1st arg - code context
                                    AstUtils.Constant(_names[i].MakeString()),               // 2nd arg - module name
                                    AstUtils.Constant(_forceAbsolute ? 0 : -1)               // 3rd arg - absolute or relative imports
                                    )
                                )
                            ),
                        _names[i].Span
                        )
                    );
            }

            statements.Add(AstUtils.Empty());
            return(GlobalParent.AddDebugInfo(Ast.Block(statements.ToReadOnlyCollection()), Span));
        }
 internal override MSAst.Expression TransformSet(SourceSpan span, MSAst.Expression right, PythonOperationKind op)
 {
     if (op == PythonOperationKind.None)
     {
         return(GlobalParent.AddDebugInfoAndVoid(
                    GlobalParent.Set(
                        _name,
                        _target,
                        right
                        ),
                    span
                    ));
     }
     else
     {
         MSAst.ParameterExpression temp = Ast.Variable(typeof(object), "inplace");
         return(GlobalParent.AddDebugInfo(
                    Ast.Block(
                        new[] { temp },
                        Ast.Assign(temp, _target),
                        SetMemberOperator(right, op, temp),
                        AstUtils.Empty()
                        ),
                    Span.Start,
                    span.End
                    ));
     }
 }
 internal override MSAst.Expression TransformDelete()
 {
     MSAst.Expression[] statements = new MSAst.Expression[_items.Length + 1];
     for (int i = 0; i < _items.Length; i++)
     {
         statements[i] = _items[i].TransformDelete();
     }
     statements[_items.Length] = AstUtils.Empty();
     return(GlobalParent.AddDebugInfo(Ast.Block(statements), Span));
 }
Exemple #7
0
        private MSAst.Expression ReduceWorker(bool optimizeDynamicConvert)
        {
            // Only the body is "in the loop" for the purposes of break/continue
            // The "else" clause is outside

            ConstantExpression constTest = _test as ConstantExpression;

            if (constTest != null && constTest.Value is int)
            {
                // while 0: / while 1:
                int val = (int)constTest.Value;
                if (val == 0)
                {
                    // completely optimize the loop away
                    if (_else == null)
                    {
                        return(MSAst.Expression.Empty());
                    }
                    else
                    {
                        return(_else);
                    }
                }

                MSAst.Expression test = MSAst.Expression.Constant(true);
                MSAst.Expression res  = AstUtils.While(
                    test,
                    _body,
                    _else,
                    _break,
                    _continue
                    );

                if (GlobalParent.IndexToLocation(_test.StartIndex).Line != GlobalParent.IndexToLocation(_body.StartIndex).Line)
                {
                    res = GlobalParent.AddDebugInfoAndVoid(res, _test.Span);
                }

                return(res);
            }

            return(AstUtils.While(
                       GlobalParent.AddDebugInfo(
                           optimizeDynamicConvert ?
                           TransformAndDynamicConvert(_test, typeof(bool)) :
                           GlobalParent.Convert(typeof(bool), Microsoft.Scripting.Actions.ConversionResultKind.ExplicitCast, _test),
                           Header
                           ),
                       _body,
                       _else,
                       _break,
                       _continue
                       ));
        }
Exemple #8
0
 protected override Ast Body(MSAst.ParameterExpression res)
 {
     return(GlobalParent.AddDebugInfo(
                Ast.Call(
                    AstMethods.SetAddForComprehension,
                    res,
                    AstUtils.Convert(_item, typeof(object))
                    ),
                _item.Span
                ));
 }
Exemple #9
0
        public override MSAst.Expression Reduce()
        {
            // Transform to series of individual del statements.
            ReadOnlyCollectionBuilder <MSAst.Expression> statements = new ReadOnlyCollectionBuilder <MSAst.Expression>(_expressions.Length + 1);

            for (int i = 0; i < _expressions.Length; i++)
            {
                statements.Add(_expressions[i].TransformDelete());
            }
            statements.Add(AstUtils.Empty());
            return(GlobalParent.AddDebugInfo(MSAst.Expression.Block(statements), Span));
        }
Exemple #10
0
 protected override Ast Body(MSAst.ParameterExpression res)
 {
     return(GlobalParent.AddDebugInfo(
                Ast.Call(
                    AstMethods.DictAddForComprehension,
                    res,
                    AstUtils.Convert(_key, typeof(object)),
                    AstUtils.Convert(_value, typeof(object))
                    ),
                new SourceSpan(_key.Span.Start, _value.Span.End)
                ));
 }
        public override MSAst.Expression Reduce()
        {
            if (Parent.IsGeneratorMethod)
            {
                // Reduce to a yield return with a marker of -2, this will be interpreted as a yield break with a return value
                return(GlobalParent.AddDebugInfo(AstUtils.YieldReturn(GeneratorLabel, TransformOrConstantNull(Expression, typeof(object)), -2), Span));
            }

            return(GlobalParent.AddDebugInfo(
                       Ast.Return(
                           FunctionDefinition._returnLabel,
                           TransformOrConstantNull(Expression, typeof(object))
                           ),
                       Span
                       ));
        }
        public override MSAst.Expression Reduce()
        {
            MSAst.Expression raiseExpression;
            if (Exception is null)
            {
                Debug.Assert(Cause is null);
                raiseExpression = Ast.Call(
                    AstMethods.MakeRethrownException,
                    Parent.LocalContext
                    );

                if (!InFinally)
                {
                    raiseExpression = Ast.Block(
                        UpdateLineUpdated(true),
                        raiseExpression
                        );
                }
            }
            else if (Cause is null)
            {
                raiseExpression = Ast.Call(
                    AstMethods.MakeException,
                    Parent.LocalContext,
                    TransformOrConstantNull(Exception, typeof(object))
                    );
            }
            else
            {
                raiseExpression = Ast.Call(
                    AstMethods.MakeExceptionWithCause,
                    Parent.LocalContext,
                    TransformOrConstantNull(Exception, typeof(object)),
                    TransformOrConstantNull(Cause, typeof(object))
                    );
            }

            return(GlobalParent.AddDebugInfo(
                       Ast.Throw(raiseExpression),
                       Span
                       ));
        }
        public override MSAst.Expression Reduce()
        {
            MSAst.ParameterExpression list = Ast.Parameter(typeof(List), "list_comprehension_list");

            // 1. Initialization code - create list and store it in the temp variable
            MSAst.Expression initialize =
                Ast.Assign(
                    list,
                    Ast.Call(AstMethods.MakeList)
                    );

            // 2. Create body from _item:   list.Append(_item)
            MSAst.Expression body = GlobalParent.AddDebugInfo(
                Ast.Call(
                    AstMethods.ListAddForComprehension,
                    list,
                    AstUtils.Convert(_item, typeof(object))
                    ),
                _item.Span
                );

            // 3. Transform all iterators in reverse order, building the true body:
            int current = _iterators.Length;

            while (current-- > 0)
            {
                ListComprehensionIterator iterator = _iterators[current];
                body = iterator.Transform(body);
            }

            return(Ast.Block(
                       new[] { list },
                       initialize,
                       body,
                       list                 // result
                       ));
        }
Exemple #14
0
        /// <summary>
        /// WithStatement is translated to the DLR AST equivalent to
        /// the following Python code snippet (from with statement spec):
        ///
        /// mgr = (EXPR)
        /// exit = mgr.__exit__  # Not calling it yet
        /// value = mgr.__enter__()
        /// exc = True
        /// try:
        ///     VAR = value  # Only if "as VAR" is present
        ///     BLOCK
        /// except:
        ///     # The exceptional case is handled here
        ///     exc = False
        ///     if not exit(*sys.exc_info()):
        ///         raise
        ///     # The exception is swallowed if exit() returns true
        /// finally:
        ///     # The normal and non-local-goto cases are handled here
        ///     if exc:
        ///         exit(None, None, None)
        ///
        /// </summary>
        public override MSAst.Expression Reduce()
        {
            // Five statements in the result...
            ReadOnlyCollectionBuilder <MSAst.Expression>          statements = new ReadOnlyCollectionBuilder <MSAst.Expression>(6);
            ReadOnlyCollectionBuilder <MSAst.ParameterExpression> variables  = new ReadOnlyCollectionBuilder <MSAst.ParameterExpression>(6);

            MSAst.ParameterExpression lineUpdated = Ast.Variable(typeof(bool), "$lineUpdated_with");
            variables.Add(lineUpdated);

            //******************************************************************
            // 1. mgr = (EXPR)
            //******************************************************************
            MSAst.ParameterExpression manager = Ast.Variable(typeof(object), "with_manager");
            variables.Add(manager);
            statements.Add(
                GlobalParent.AddDebugInfo(
                    Ast.Assign(
                        manager,
                        _contextManager
                        ),
                    new SourceSpan(Start, _header)
                    )
                );

            //******************************************************************
            // 2. exit = mgr.__exit__  # Not calling it yet
            //******************************************************************
            MSAst.ParameterExpression exit = Ast.Variable(typeof(object), "with_exit");
            variables.Add(exit);
            statements.Add(
                MakeAssignment(
                    exit,
                    GlobalParent.Get(
                        "__exit__",
                        manager
                        )
                    )
                );

            //******************************************************************
            // 3. value = mgr.__enter__()
            //******************************************************************
            MSAst.ParameterExpression value = Ast.Variable(typeof(object), "with_value");
            variables.Add(value);
            statements.Add(
                GlobalParent.AddDebugInfoAndVoid(
                    MakeAssignment(
                        value,
                        Parent.Invoke(
                            new CallSignature(0),
                            Parent.LocalContext,
                            GlobalParent.Get(
                                "__enter__",
                                manager
                                )
                            )
                        ),
                    new SourceSpan(Start, _header)
                    )
                );

            //******************************************************************
            // 4. exc = True
            //******************************************************************
            MSAst.ParameterExpression exc = Ast.Variable(typeof(bool), "with_exc");
            variables.Add(exc);
            statements.Add(
                MakeAssignment(
                    exc,
                    AstUtils.Constant(true)
                    )
                );

            //******************************************************************
            //  5. The final try statement:
            //
            //  try:
            //      VAR = value  # Only if "as VAR" is present
            //      BLOCK
            //  except:
            //      # The exceptional case is handled here
            //      exc = False
            //      if not exit(*sys.exc_info()):
            //          raise
            //      # The exception is swallowed if exit() returns true
            //  finally:
            //      # The normal and non-local-goto cases are handled here
            //      if exc:
            //          exit(None, None, None)
            //******************************************************************

            MSAst.ParameterExpression exception;
            MSAst.ParameterExpression nestedFrames = Ast.Variable(typeof(List <DynamicStackFrame>), "$nestedFrames");
            variables.Add(nestedFrames);
            statements.Add(
                // try:
                AstUtils.Try(
                    AstUtils.Try(// try statement body
                        PushLineUpdated(false, lineUpdated),
                        _var != null ?
                        (MSAst.Expression)Ast.Block(
                            // VAR = value
                            _var.TransformSet(SourceSpan.None, value, PythonOperationKind.None),
                            // BLOCK
                            _body,
                            AstUtils.Empty()
                            ) :
                        // BLOCK
                        (MSAst.Expression)_body // except:, // try statement location
                        ).Catch(exception = Ast.Variable(typeof(Exception), "exception"),
                                                // Python specific exception handling code
                                TryStatement.GetTracebackHeader(
                                    this,
                                    exception,
                                    GlobalParent.AddDebugInfoAndVoid(
                                        Ast.Block(
                                            // exc = False
                                            MakeAssignment(
                                                exc,
                                                AstUtils.Constant(false)
                                                ),
                                            Ast.Assign(
                                                nestedFrames,
                                                Ast.Call(AstMethods.GetAndClearDynamicStackFrames)
                                                ),
                                            //  if not exit(*sys.exc_info()):
                                            //      raise
                                            AstUtils.IfThen(
                                                GlobalParent.Convert(
                                                    typeof(bool),
                                                    ConversionResultKind.ExplicitCast,
                                                    GlobalParent.Operation(
                                                        typeof(bool),
                                                        PythonOperationKind.IsFalse,
                                                        MakeExitCall(exit, exception)
                                                        )
                                                    ),
                                                UpdateLineUpdated(true),
                                                Ast.Call(
                                                    AstMethods.SetDynamicStackFrames,
                                                    nestedFrames
                                                    ),
                                                Ast.Throw(
                                                    Ast.Call(
                                                        AstMethods.MakeRethrowExceptionWorker,
                                                        exception
                                                        )
                                                    )
                                                )
                                            ),
                                        _body.Span
                                        )
                                    ),
                                Ast.Call(
                                    AstMethods.SetDynamicStackFrames,
                                    nestedFrames
                                    ),
                                PopLineUpdated(lineUpdated),
                                Ast.Empty()
                                )
                    // finally:
                    ).Finally(
                    //  if exc:
                    //      exit(None, None, None)
                    AstUtils.IfThen(
                        exc,
                        GlobalParent.AddDebugInfoAndVoid(
                            Ast.Block(
                                Ast.Dynamic(
                                    GlobalParent.PyContext.Invoke(
                                        new CallSignature(3)        // signature doesn't include function
                                        ),
                                    typeof(object),
                                    new MSAst.Expression[] {
                Parent.LocalContext,
                exit,
                AstUtils.Constant(null),
                AstUtils.Constant(null),
                AstUtils.Constant(null)
            }
                                    ),
                                Ast.Empty()
                                ),
                            _contextManager.Span
                            )
                        )
                    )
                );

            statements.Add(AstUtils.Empty());
            return(Ast.Block(variables.ToReadOnlyCollection(), statements.ToReadOnlyCollection()));
        }
        /// <summary>
        /// Creates the LambdaExpression which implements the body of the function.
        ///
        /// The functions signature is either "object Function(PythonFunction, ...)"
        /// where there is one object parameter for each user defined parameter or
        /// object Function(PythonFunction, object[]) for functions which take more
        /// than PythonCallTargets.MaxArgs arguments.
        /// </summary>
        private LightLambdaExpression CreateFunctionLambda()
        {
            bool needsWrapperMethod = _parameters.Length > PythonCallTargets.MaxArgs;
            Type delegateType       = GetDelegateType(_parameters, needsWrapperMethod, out _);

            MSAst.ParameterExpression localContext = null;
            ReadOnlyCollectionBuilder <MSAst.ParameterExpression> locals = new ReadOnlyCollectionBuilder <MSAst.ParameterExpression>();

            if (NeedsLocalContext)
            {
                localContext = LocalCodeContextVariable;
                locals.Add(localContext);
            }

            MSAst.ParameterExpression[] parameters = CreateParameters(needsWrapperMethod, locals);

            List <MSAst.Expression> init = new List <MSAst.Expression>();

            foreach (var param in _parameters)
            {
                if (GetVariableExpression(param.PythonVariable) is IPythonVariableExpression pyVar)
                {
                    var varInit = pyVar.Create();
                    if (varInit != null)
                    {
                        init.Add(varInit);
                    }
                }
            }

            // Transform the parameters.
            init.Add(Ast.ClearDebugInfo(GlobalParent.Document));

            locals.Add(PythonAst._globalContext);
            init.Add(Ast.Assign(PythonAst._globalContext, new GetGlobalContextExpression(_parentContext)));

            GlobalParent.PrepareScope(locals, init);

            // Create variables and references. Since references refer to
            // parameters, do this after parameters have been created.

            CreateFunctionVariables(locals, init);

            // Initialize parameters - unpack tuples.
            // Since tuples unpack into locals, this must be done after locals have been created.
            InitializeParameters(init, needsWrapperMethod, parameters);

            List <MSAst.Expression> statements = new List <MSAst.Expression>();
            // add beginning sequence point
            var start = GlobalParent.IndexToLocation(StartIndex);

            statements.Add(GlobalParent.AddDebugInfo(
                               AstUtils.Empty(),
                               new SourceSpan(new SourceLocation(0, start.Line, start.Column), new SourceLocation(0, start.Line, int.MaxValue))));


            // For generators, we need to do a check before the first statement for Generator.Throw() / Generator.Close().
            // The exception traceback needs to come from the generator's method body, and so we must do the check and throw
            // from inside the generator.
            if (IsGenerator)
            {
                MSAst.Expression s1 = YieldExpression.CreateCheckThrowExpression(SourceSpan.None);
                statements.Add(s1);
            }

            if (Body.CanThrow && !(Body is SuiteStatement) && Body.StartIndex != -1)
            {
                statements.Add(UpdateLineNumber(GlobalParent.IndexToLocation(Body.StartIndex).Line));
            }

            statements.Add(Body);
            MSAst.Expression body = Ast.Block(statements);

            if (Body.CanThrow && GlobalParent.PyContext.PythonOptions.Frames)
            {
                body = AddFrame(LocalContext, Ast.Property(_functionParam, typeof(PythonFunction).GetProperty(nameof(PythonFunction.__code__))), body);
                locals.Add(FunctionStackVariable);
            }

            body = AddProfiling(body);
            body = WrapScopeStatements(body, Body.CanThrow);
            body = Ast.Block(body, AstUtils.Empty());
            body = AddReturnTarget(body);

            MSAst.Expression bodyStmt = body;
            if (localContext != null)
            {
                var createLocal = CreateLocalContext(_parentContext);

                init.Add(
                    Ast.Assign(
                        localContext,
                        createLocal
                        )
                    );
            }

            init.Add(bodyStmt);

            bodyStmt = Ast.Block(init);

            // wrap a scope if needed
            bodyStmt = Ast.Block(locals.ToReadOnlyCollection(), bodyStmt);

            return(AstUtils.LightLambda(
                       typeof(object),
                       delegateType,
                       AddDefaultReturn(bodyStmt, typeof(object)),
                       Name + "$" + Interlocked.Increment(ref _lambdaId),
                       parameters
                       ));
        }
Exemple #16
0
        public override MSAst.Expression Reduce()
        {
            // allocated all variables here so they won't be shared w/ other
            // locals allocated during the body or except blocks.
            MSAst.ParameterExpression lineUpdated = null;
            MSAst.ParameterExpression runElse     = null;

            if (_else != null || (_handlers != null && _handlers.Length > 0))
            {
                lineUpdated = Ast.Variable(typeof(bool), "$lineUpdated_try");
                if (_else != null)
                {
                    runElse = Ast.Variable(typeof(bool), "run_else");
                }
            }

            // don't allocate locals below here...
            MSAst.Expression          body = _body;
            MSAst.Expression          @else = _else;
            MSAst.Expression          @catch, result;
            MSAst.ParameterExpression exception;

            if (_handlers != null && _handlers.Length > 0)
            {
                exception = Ast.Variable(typeof(Exception), "$exception");
                @catch    = TransformHandlers(exception);
            }
            else
            {
                exception = null;
                @catch    = null;
            }

            // We have else clause, must generate guard around it
            if (@else != null)
            {
                Debug.Assert(@catch != null);

                //  run_else = true;
                //  try {
                //      try_body
                //  } catch ( ... ) {
                //      run_else = false;
                //      catch_body
                //  }
                //  if (run_else) {
                //      else_body
                //  }
                result =
                    Ast.Block(
                        Ast.Assign(runElse, AstUtils.Constant(true)),
                        // save existing line updated, we could choose to do this only for nested exception handlers.
                        PushLineUpdated(false, lineUpdated),
                        AstUtils.Try(
                            Parent.AddDebugInfo(AstUtils.Empty(), new SourceSpan(Span.Start, _header)),
                            body
                            ).Catch(exception,
                                    Ast.Assign(runElse, AstUtils.Constant(false)),
                                    @catch,
                                    // restore existing line updated after exception handler completes
                                    PopLineUpdated(lineUpdated),
                                    Ast.Assign(exception, Ast.Constant(null, typeof(Exception))),
                                    AstUtils.Default(body.Type)
                                    ),
                        AstUtils.IfThen(runElse,
                                        @else
                                        ),
                        AstUtils.Empty()
                        );
            }
            else if (@catch != null)            // no "else" clause
            //  try {
            //      <try body>
            //  } catch (Exception e) {
            //      ... catch handling ...
            //  }
            //
            {
                result =
                    AstUtils.Try(
                        GlobalParent.AddDebugInfo(AstUtils.Empty(), new SourceSpan(Span.Start, _header)),
                        // save existing line updated
                        PushLineUpdated(false, lineUpdated),
                        body
                        ).Catch(exception,
                                @catch,
                                // restore existing line updated after exception handler completes
                                PopLineUpdated(lineUpdated),
                                Ast.Call(AstMethods.ExceptionHandled, Parent.LocalContext),
                                Ast.Assign(exception, Ast.Constant(null, typeof(Exception))),
                                AstUtils.Default(body.Type)
                                );
            }
            else
            {
                result = body;
            }

            return(Ast.Block(
                       GetVariables(lineUpdated, runElse),
                       AddFinally(result)
                       ));
        }
Exemple #17
0
        /// <summary>
        /// Transform multiple python except handlers for a try block into a single catch body.
        /// </summary>
        /// <param name="exception">The variable for the exception in the catch block.</param>
        /// <returns>Null if there are no except handlers. Else the statement to go inside the catch handler</returns>
        private MSAst.Expression TransformHandlers(MSAst.ParameterExpression exception)
        {
            Assert.NotEmpty(_handlers);

            MSAst.ParameterExpression extracted = Ast.Variable(typeof(object), "$extracted");

            var tests = new List <Microsoft.Scripting.Ast.IfStatementTest>(_handlers.Length);

            MSAst.ParameterExpression converted = null;
            MSAst.Expression          catchAll  = null;

            for (int index = 0; index < _handlers.Length; index++)
            {
                TryStatementHandler tsh = _handlers[index];

                if (tsh.Test != null)
                {
                    Microsoft.Scripting.Ast.IfStatementTest ist;

                    //  translating:
                    //      except Test ...
                    //
                    //  generate following AST for the Test (common part):
                    //      CheckException(exception, Test)
                    MSAst.Expression test =
                        Ast.Call(
                            AstMethods.CheckException,
                            Parent.LocalContext,
                            extracted,
                            AstUtils.Convert(tsh.Test, typeof(object))
                            );

                    if (tsh.Target != null)
                    {
                        //  translating:
                        //      except Test, Target:
                        //          <body>
                        //  into:
                        //      if ((converted = CheckException(exception, Test)) != null) {
                        //          Target = converted;
                        //          traceback-header
                        //          <body>
                        //      }

                        if (converted == null)
                        {
                            converted = Ast.Variable(typeof(object), "$converted");
                        }

                        ist = AstUtils.IfCondition(
                            Ast.NotEqual(
                                Ast.Assign(converted, test),
                                AstUtils.Constant(null)
                                ),
                            Ast.Block(
                                tsh.Target.TransformSet(SourceSpan.None, converted, PythonOperationKind.None),
                                GlobalParent.AddDebugInfo(
                                    GetTracebackHeader(
                                        this,
                                        exception,
                                        tsh.Body
                                        ),
                                    new SourceSpan(tsh.Start, tsh.Header)
                                    ),
                                AstUtils.Empty()
                                )
                            );
                    }
                    else
                    {
                        //  translating:
                        //      except Test:
                        //          <body>
                        //  into:
                        //      if (CheckException(exception, Test) != null) {
                        //          traceback-header
                        //          <body>
                        //      }
                        ist = AstUtils.IfCondition(
                            Ast.NotEqual(
                                test,
                                AstUtils.Constant(null)
                                ),
                            GlobalParent.AddDebugInfo(
                                GetTracebackHeader(
                                    this,
                                    exception,
                                    tsh.Body
                                    ),
                                new SourceSpan(tsh.Start, tsh.Header)
                                )
                            );
                    }

                    // Add the test to the if statement test cascade
                    tests.Add(ist);
                }
                else
                {
                    Debug.Assert(index == _handlers.Length - 1);
                    Debug.Assert(catchAll == null);

                    //  translating:
                    //      except:
                    //          <body>
                    //  into:
                    //  {
                    //          traceback-header
                    //          <body>
                    //  }

                    catchAll = GlobalParent.AddDebugInfo(
                        GetTracebackHeader(this, exception, tsh.Body),
                        new SourceSpan(tsh.Start, tsh.Header)
                        );
                }
            }

            MSAst.Expression body = null;

            if (tests.Count > 0)
            {
                // rethrow the exception if we have no catch-all block
                if (catchAll == null)
                {
                    catchAll = Ast.Block(
                        Parent.GetSaveLineNumberExpression(exception, true),
                        Ast.Throw(
                            Ast.Call(
                                typeof(ExceptionHelpers).GetMethod("UpdateForRethrow"),
                                exception
                                )
                            )
                        );
                }

                body = AstUtils.If(
                    tests.ToArray(),
                    catchAll
                    );
            }
            else
            {
                Debug.Assert(catchAll != null);
                body = catchAll;
            }

            IList <MSAst.ParameterExpression> args;

            if (converted != null)
            {
                args = new ReadOnlyCollectionBuilder <MSAst.ParameterExpression> {
                    converted, extracted
                };
            }
            else
            {
                args = new ReadOnlyCollectionBuilder <MSAst.ParameterExpression> {
                    extracted
                };
            }

            // Codegen becomes:
            //     extracted = PythonOps.SetCurrentException(exception)
            //      < dynamic exception analysis >
            return(Ast.Block(
                       args,
                       Ast.Assign(
                           extracted,
                           Ast.Call(
                               AstMethods.SetCurrentException,
                               Parent.LocalContext,
                               exception
                               )
                           ),
                       body,
                       Ast.Assign(extracted, Ast.Constant(null)),
                       AstUtils.Empty()
                       ));
        }
        internal override MSAst.Expression TransformSet(SourceSpan span, MSAst.Expression right, PythonOperationKind op)
        {
            // if we just have a simple named multi-assignment  (e.g. a, b = 1,2)
            // then go ahead and step over the entire statement at once.  If we have a
            // more complex statement (e.g. a.b, c.d = 1, 2) then we'll step over the
            // sets individually as they could be property sets the user wants to step
            // into.  TODO: Enable stepping of the right hand side?
            bool emitIndividualSets = false;

            foreach (Expression e in _items)
            {
                if (IsComplexAssignment(e))
                {
                    emitIndividualSets = true;
                    break;
                }
            }

            SourceSpan rightSpan = SourceSpan.None;
            SourceSpan leftSpan  =
                (Span.Start.IsValid && span.IsValid) ?
                new SourceSpan(Span.Start, span.End) :
                SourceSpan.None;

            SourceSpan totalSpan = SourceSpan.None;

            if (emitIndividualSets)
            {
                rightSpan = span;
                leftSpan  = SourceSpan.None;
                totalSpan = (Span.Start.IsValid && span.IsValid) ?
                            new SourceSpan(Span.Start, span.End) :
                            SourceSpan.None;
            }

            // 1. Evaluate the expression and assign the value to the temp.
            MSAst.ParameterExpression right_temp = Ast.Variable(typeof(object), "unpacking");

            // 2. Add the assignment "right_temp = right" into the suite/block
            MSAst.Expression assignStmt1 = MakeAssignment(right_temp, right);

            // 3. Call GetEnumeratorValues on the right side (stored in temp)
            MSAst.Expression enumeratorValues = Expression.Convert(LightExceptions.CheckAndThrow(
                                                                       Expression.Call(
                                                                           emitIndividualSets ?
                                                                           AstMethods.GetEnumeratorValues :
                                                                           AstMethods.GetEnumeratorValuesNoComplexSets, // method
                                                                           // arguments
                                                                           Parent.LocalContext,
                                                                           right_temp,
                                                                           AstUtils.Constant(_items.Length)
                                                                           )
                                                                       ), typeof(object[]));

            // 4. Create temporary variable for the array
            MSAst.ParameterExpression array_temp = Ast.Variable(typeof(object[]), "array");

            // 5. Assign the value of the method call (mce) into the array temp
            // And add the assignment "array_temp = Ops.GetEnumeratorValues(...)" into the block
            MSAst.Expression assignStmt2 = MakeAssignment(
                array_temp,
                enumeratorValues,
                rightSpan
                );

            ReadOnlyCollectionBuilder <MSAst.Expression> sets = new ReadOnlyCollectionBuilder <MSAst.Expression>(_items.Length + 1);

            for (int i = 0; i < _items.Length; i++)
            {
                // target = array_temp[i]

                Expression target = _items[i];
                if (target == null)
                {
                    continue;
                }

                // 6. array_temp[i]
                MSAst.Expression element = Ast.ArrayAccess(
                    array_temp,                             // array expression
                    AstUtils.Constant(i)                    // index
                    );

                // 7. target = array_temp[i], and add the transformed assignment into the list of sets
                MSAst.Expression set = target.TransformSet(
                    emitIndividualSets ?                    // span
                    target.Span :
                    SourceSpan.None,
                    element,
                    PythonOperationKind.None
                    );
                sets.Add(set);
            }
            // 9. add the sets as their own block so they can be marked as a single span, if necessary.
            sets.Add(AstUtils.Empty());
            MSAst.Expression itemSet = GlobalParent.AddDebugInfo(Ast.Block(sets.ToReadOnlyCollection()), leftSpan);

            // 10. Return the suite statement (block)
            return(GlobalParent.AddDebugInfo(Ast.Block(new[] { array_temp, right_temp }, assignStmt1, assignStmt2, itemSet, AstUtils.Empty()), totalSpan));
        }
Exemple #19
0
        public override MSAst.Expression Reduce()
        {
            MSAst.Expression destination = _dest;

            if (_expressions.Length == 0)
            {
                MSAst.Expression result;
                if (destination != null)
                {
                    result = Ast.Call(
                        AstMethods.PrintNewlineWithDest,
                        Parent.LocalContext,
                        destination
                        );
                }
                else
                {
                    result = Ast.Call(
                        AstMethods.PrintNewline,
                        Parent.LocalContext
                        );
                }
                return(GlobalParent.AddDebugInfo(result, Span));
            }
            else
            {
                // Create list for the individual statements
                ReadOnlyCollectionBuilder <MSAst.Expression> statements = new ReadOnlyCollectionBuilder <MSAst.Expression>();

                // Store destination in a temp, if we have one
                MSAst.ParameterExpression temp = null;
                if (destination != null)
                {
                    temp = Ast.Variable(typeof(object), "destination");

                    statements.Add(MakeAssignment(temp, destination));

                    destination = temp;
                }
                for (int i = 0; i < _expressions.Length; i++)
                {
                    bool       withComma = (i < _expressions.Length - 1 || _trailingComma);// ? "PrintComma" : "Print";
                    Expression current   = _expressions[i];
                    MSAst.MethodCallExpression mce;

                    if (destination != null)
                    {
                        mce = Ast.Call(
                            withComma ? AstMethods.PrintCommaWithDest : AstMethods.PrintWithDest,
                            Parent.LocalContext,
                            destination,
                            AstUtils.Convert(current, typeof(object))
                            );
                    }
                    else
                    {
                        mce = Ast.Call(
                            withComma ? AstMethods.PrintComma : AstMethods.Print,
                            Parent.LocalContext,
                            AstUtils.Convert(current, typeof(object))
                            );
                    }

                    statements.Add(mce);
                }

                statements.Add(AstUtils.Empty());
                MSAst.Expression res;
                if (temp != null)
                {
                    res = Ast.Block(new[] { temp }, statements.ToReadOnlyCollection());
                }
                else
                {
                    res = Ast.Block(statements.ToReadOnlyCollection());
                }
                return(GlobalParent.AddDebugInfo(res, Span));
            }
        }
Exemple #20
0
        /// <summary>
        /// Creates the LambdaExpression which implements the body of the function.
        ///
        /// The functions signature is either "object Function(PythonFunction, ...)"
        /// where there is one object parameter for each user defined parameter or
        /// object Function(PythonFunction, object[]) for functions which take more
        /// than PythonCallTargets.MaxArgs arguments.
        /// </summary>
        private LightLambdaExpression CreateFunctionLambda()
        {
            bool     needsWrapperMethod = _parameters.Length > PythonCallTargets.MaxArgs;
            Delegate originalDelegate;
            Type     delegateType = GetDelegateType(_parameters, needsWrapperMethod, out originalDelegate);

            MSAst.ParameterExpression localContext = null;
            ReadOnlyCollectionBuilder <MSAst.ParameterExpression> locals = new ReadOnlyCollectionBuilder <MSAst.ParameterExpression>();

            if (NeedsLocalContext)
            {
                localContext = LocalCodeContextVariable;
                locals.Add(localContext);
            }

            MSAst.ParameterExpression[] parameters = CreateParameters(needsWrapperMethod, locals);

            List <MSAst.Expression> init = new List <MSAst.Expression>();

            foreach (var param in _parameters)
            {
                IPythonVariableExpression pyVar = GetVariableExpression(param.PythonVariable) as IPythonVariableExpression;
                if (pyVar != null)
                {
                    var varInit = pyVar.Create();
                    if (varInit != null)
                    {
                        init.Add(varInit);
                    }
                }
            }

            // Transform the parameters.
            init.Add(Ast.ClearDebugInfo(GlobalParent.Document));

            locals.Add(PythonAst._globalContext);
            init.Add(Ast.Assign(PythonAst._globalContext, new GetGlobalContextExpression(_parentContext)));

            GlobalParent.PrepareScope(locals, init);

            // Create variables and references. Since references refer to
            // parameters, do this after parameters have been created.

            CreateFunctionVariables(locals, init);

            // If the __class__ variable is used the a class method then we need to initialize it.
            // This must be done before parameter initialization (in case one of the parameters is called __class__).
            ClassDefinition parent = FindParentOfType <ClassDefinition>();
            PythonVariable  pVar;

            if (parent != null && TryGetVariable("__class__", out pVar))
            {
                init.Add(
                    AssignValue(
                        GetVariableExpression(pVar),
                        Ast.Call(AstMethods.LookupName, parent.Parent.LocalContext, Ast.Constant(parent.Name))
                        )
                    );
            }

            // Initialize parameters - unpack tuples.
            // Since tuples unpack into locals, this must be done after locals have been created.
            InitializeParameters(init, needsWrapperMethod, parameters);

            List <MSAst.Expression> statements = new List <MSAst.Expression>();
            // add beginning sequence point
            var start = GlobalParent.IndexToLocation(StartIndex);

            statements.Add(GlobalParent.AddDebugInfo(
                               AstUtils.Empty(),
                               new SourceSpan(new SourceLocation(0, start.Line, start.Column), new SourceLocation(0, start.Line, Int32.MaxValue))));


            // For generators, we need to do a check before the first statement for Generator.Throw() / Generator.Close().
            // The exception traceback needs to come from the generator's method body, and so we must do the check and throw
            // from inside the generator.
            if (IsGenerator)
            {
                MSAst.Expression s1 = YieldExpression.CreateCheckThrowExpression(SourceSpan.None);
                statements.Add(s1);
            }

            MSAst.ParameterExpression extracted = null;
            if (!IsGenerator && _canSetSysExcInfo)
            {
                // need to allocate the exception here so we don't share w/ exceptions made & freed
                // during the body.
                extracted = Ast.Parameter(typeof(Exception), "$ex");
                locals.Add(extracted);
            }

            if (_body.CanThrow && !(_body is SuiteStatement) && _body.StartIndex != -1)
            {
                statements.Add(UpdateLineNumber(GlobalParent.IndexToLocation(_body.StartIndex).Line));
            }

            statements.Add(Body);
            MSAst.Expression body = Ast.Block(statements);

            // If this function can modify sys.exc_info() (_canSetSysExcInfo), then it must restore the result on finish.
            //
            // Wrap in
            //   $temp = PythonOps.SaveCurrentException()
            //   <body>
            //   PythonOps.RestoreCurrentException($temp)
            // Skip this if we're a generator. For generators, the try finally is handled by the PythonGenerator class
            //  before it's invoked. This is because the restoration must occur at every place the function returns from
            //  a yield point. That's different than the finally semantics in a generator.
            if (extracted != null)
            {
                MSAst.Expression s = AstUtils.Try(
                    Ast.Assign(
                        extracted,
                        Ast.Call(AstMethods.SaveCurrentException)
                        ),
                    body
                    ).Finally(
                    Ast.Call(
                        AstMethods.RestoreCurrentException, extracted
                        )
                    );
                body = s;
            }

            if (_body.CanThrow && GlobalParent.PyContext.PythonOptions.Frames)
            {
                body = AddFrame(LocalContext, Ast.Property(_functionParam, typeof(PythonFunction).GetProperty("__code__")), body);
                locals.Add(FunctionStackVariable);
            }

            body = AddProfiling(body);
            body = WrapScopeStatements(body, _body.CanThrow);
            body = Ast.Block(body, AstUtils.Empty());
            body = AddReturnTarget(body);


            MSAst.Expression bodyStmt = body;
            if (localContext != null)
            {
                var createLocal = CreateLocalContext(_parentContext);

                init.Add(
                    Ast.Assign(
                        localContext,
                        createLocal
                        )
                    );
            }

            init.Add(bodyStmt);

            bodyStmt = Ast.Block(init);

            // wrap a scope if needed
            bodyStmt = Ast.Block(locals.ToReadOnlyCollection(), bodyStmt);

            return(AstUtils.LightLambda(
                       typeof(object),
                       delegateType,
                       AddDefaultReturn(bodyStmt, typeof(object)),
                       Name + "$" + Interlocked.Increment(ref _lambdaId),
                       parameters
                       ));
        }
Exemple #21
0
 public override MSAst.Expression Reduce()
 {
     return(GlobalParent.AddDebugInfo(MSAst.Expression.Continue(_loop.ContinueLabel), Span));
 }
        public override MSAst.Expression Reduce()
        {
            if (_names == _star)
            {
                // from a[.b] import *
                return(GlobalParent.AddDebugInfo(
                           Ast.Call(
                               AstMethods.ImportStar,
                               Parent.LocalContext,
                               AstUtils.Constant(_root.MakeString()),
                               AstUtils.Constant(GetLevel())
                               ),
                           Span
                           ));
            }
            else
            {
                // from a[.b] import x [as xx], [ y [ as yy] ] [ , ... ]

                ReadOnlyCollectionBuilder <MSAst.Expression> statements = new ReadOnlyCollectionBuilder <MSAst.Expression>();
                MSAst.ParameterExpression module = Ast.Variable(typeof(object), "module");

                // Create initializer of the array of names being passed to ImportWithNames
                MSAst.Expression[] names = new MSAst.Expression[_names.Length];
                for (int i = 0; i < names.Length; i++)
                {
                    names[i] = AstUtils.Constant(_names[i]);
                }

                // module = PythonOps.ImportWithNames(<context>, _root, make_array(_names))
                statements.Add(
                    GlobalParent.AddDebugInfoAndVoid(
                        AssignValue(
                            module,
                            LightExceptions.CheckAndThrow(
                                Expression.Call(
                                    AstMethods.ImportWithNames,
                                    Parent.LocalContext,
                                    AstUtils.Constant(_root.MakeString()),
                                    Ast.NewArrayInit(typeof(string), names),
                                    AstUtils.Constant(GetLevel())
                                    )
                                )
                            ),
                        _root.Span
                        )
                    );

                // now load all the names being imported and assign the variables
                for (int i = 0; i < names.Length; i++)
                {
                    statements.Add(
                        GlobalParent.AddDebugInfoAndVoid(
                            AssignValue(
                                Parent.GetVariableExpression(_variables[i]),
                                Ast.Call(
                                    AstMethods.ImportFrom,
                                    Parent.LocalContext,
                                    module,
                                    names[i]
                                    )
                                ),
                            Span
                            )
                        );
                }

                statements.Add(AstUtils.Empty());
                return(GlobalParent.AddDebugInfo(Ast.Block(new[] { module }, statements.ToArray()), Span));
            }
        }
 public override MSAst.Expression Reduce()
 {
     return(GlobalParent.AddDebugInfo(MSAst.Expression.Break(_loop.BreakLabel), Span));
 }
Exemple #24
0
        public override MSAst.Expression Reduce()
        {
            // allocated all variables here so they won't be shared w/ other
            // locals allocated during the body or except blocks.
            MSAst.ParameterExpression?lineUpdated = null;
            MSAst.ParameterExpression?runElse     = null;
            MSAst.ParameterExpression?previousExceptionContext = null;

            Debug.Assert(Else is null || _handlers.Length > 0);

            if (_handlers.Length > 0)
            {
                lineUpdated = Ast.Variable(typeof(bool), "$lineUpdated_try");
                if (Else != null)
                {
                    runElse = Ast.Variable(typeof(bool), "run_else");
                }
            }

            // don't allocate locals below here...
            MSAst.Expression          body  = Body;
            MSAst.Expression?         @else = Else;
            MSAst.Expression?         @catch;
            MSAst.Expression          result;
            MSAst.ParameterExpression?exception;

            if (_handlers.Length > 0)
            {
                previousExceptionContext = Ast.Variable(typeof(Exception), "$previousException");
                exception = Ast.Variable(typeof(Exception), "$exception");
                @catch    = TransformHandlers(exception, previousExceptionContext);
            }
            else if (Finally != null)
            {
                exception = Ast.Variable(typeof(Exception), "$exception");
                @catch    = null;
            }
            else
            {
                exception = null;
                @catch    = null;
            }

            // We have else clause, must generate guard around it
            if (@else != null)
            {
                Debug.Assert(runElse != null);
                Debug.Assert(previousExceptionContext != null && exception != null && @catch != null);

                //  run_else = true;
                //  try {
                //      try_body
                //  } catch ( ... ) {
                //      run_else = false;
                //      catch_body
                //  }
                //  if (run_else) {
                //      else_body
                //  }
                result =
                    Ast.Block(
                        Ast.Assign(runElse, AstUtils.Constant(true)),
                        // save existing line updated, we could choose to do this only for nested exception handlers.
                        PushLineUpdated(false, lineUpdated),
                        LightExceptions.RewriteExternal(
                            AstUtils.Try(
                                Parent.AddDebugInfo(AstUtils.Empty(), new SourceSpan(Span.Start, GlobalParent.IndexToLocation(HeaderIndex))),
                                Ast.Assign(previousExceptionContext, Ast.Call(AstMethods.SaveCurrentException)),
                                body,
                                AstUtils.Constant(null)
                                ).Catch(exception,
                                        Ast.Assign(runElse, AstUtils.Constant(false)),
                                        @catch,
                                        // restore existing line updated after exception handler completes
                                        PopLineUpdated(lineUpdated),
                                        Ast.Assign(exception, Ast.Constant(null, typeof(Exception))),
                                        AstUtils.Constant(null)
                                        )
                            ),
                        AstUtils.IfThen(runElse,
                                        @else
                                        ),
                        AstUtils.Empty()
                        );
            }
            else if (@catch != null)            // no "else" clause
            //  try {
            //      <try body>
            //  } catch (Exception e) {
            //      ... catch handling ...
            //  }
            //
            {
                Debug.Assert(previousExceptionContext != null && exception != null);

                result =
                    LightExceptions.RewriteExternal(
                        AstUtils.Try(
                            GlobalParent.AddDebugInfo(AstUtils.Empty(), new SourceSpan(Span.Start, GlobalParent.IndexToLocation(HeaderIndex))),
                            // save existing line updated
                            PushLineUpdated(false, lineUpdated),
                            Ast.Assign(previousExceptionContext, Ast.Call(AstMethods.SaveCurrentException)),
                            body,
                            AstUtils.Constant(null)
                            ).Catch(exception,
                                    @catch,
                                    // restore existing line updated after exception handler completes
                                    PopLineUpdated(lineUpdated),
                                    Ast.Assign(exception, Ast.Constant(null, typeof(Exception))),
                                    AstUtils.Constant(null)
                                    )
                        );
            }
            else
            {
                result = body;
            }

            return(Ast.Block(
                       GetVariables(lineUpdated, runElse, previousExceptionContext),
                       AddFinally(result),
                       AstUtils.Default(typeof(void))
                       ));
        }