Exemple #1
0
        internal override MSAst.Expression Transform(AstGenerator ag) {
            if (ag.IsGenerator) {
                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 ag.AddDebugInfo(AstUtils.YieldBreak(ag.GeneratorLabel), Span);
            }

            return ag.AddDebugInfo(
                Ast.Return(
                    ag.ReturnLabel,
                    ag.TransformOrConstantNull(_expression, typeof(object))
                ),
                Span
            );
        }
Exemple #2
0
        internal override MSAst.Expression Transform(AstGenerator ag) {
            List<MSAst.Expression> statements = new List<MSAst.Expression>();

            for (int i = 0; i < _names.Length; i++) {
                statements.Add(
                    // _references[i] = PythonOps.Import(<code context>, _names[i])
                    ag.AddDebugInfo(
                        AstUtils.Assign(
                            _variables[i].Variable, 
                            Ast.Call(
                                AstGenerator.GetHelperMethod(                           // helper
                                    _asNames[i] == SymbolId.Empty ? "ImportTop" : "ImportBottom"
                                ),
                                AstUtils.CodeContext(),                                 // 1st arg - code context
                                Ast.Constant(_names[i].MakeString()),                   // 2nd arg - module name
                                Ast.Constant(_forceAbsolute ? 0 : -1)                   // 3rd arg - absolute or relative imports
                            )
                        ),
                        _names[i].Span
                    )
                );
            }

            statements.Add(Ast.Empty());
            return ag.AddDebugInfo(Ast.Block(statements.ToArray()), Span);
        }
 internal override MSAst.Expression TransformSet(AstGenerator ag, SourceSpan span, MSAst.Expression right, Operators op) {
     if (op == Operators.None) {
         return ag.AddDebugInfoAndVoid(
             Binders.Set(
                 ag.BinderState,
                 typeof(object),
                 SymbolTable.IdToString(_name),
                 ag.Transform(_target),
                 right
             ),
             span
         );
     } else {
         MSAst.ParameterExpression temp = ag.GetTemporary("inplace");
         return ag.AddDebugInfo(
             Ast.Block(
                 Ast.Assign(temp, ag.Transform(_target)),
                 SetMemberOperator(ag, right, op, temp),
                 Ast.Empty()
             ),
             Span.Start,
             span.End
         );
     }
 }
        internal override MSAst.Expression Transform(AstGenerator ag) {
            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])
                    ag.AddDebugInfoAndVoid(
                        GlobalAllocator.Assign(
                            ag.Globals.GetVariable(ag, _variables[i]), 
                            Ast.Call(
                                AstGenerator.GetHelperMethod(                           // helper
                                    _asNames[i] == null ? "ImportTop" : "ImportBottom"
                                ),
                                ag.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 ag.AddDebugInfo(Ast.Block(statements.ToReadOnlyCollection()), Span);
        }
Exemple #5
0
 internal override MSAst.Expression Transform(AstGenerator ag) {
     if (ag.InLoop) {
         return ag.AddDebugInfo(MSAst.Expression.Break(ag.BreakLabel), Span);
     } else {
         return null;
     }
 }
        internal override MSAst.Expression Transform(AstGenerator ag, Type type) {
            MSAst.ParameterExpression list = ag.GetTemporary("list_comprehension_list", typeof(List));

            // 1. Initialization code - create list and store it in the temp variable
            MSAst.Expression initialize =
                Ast.Assign(
                    list,
                    Ast.Call(
                        AstGenerator.GetHelperMethod("MakeList", Type.EmptyTypes) // method
                    )                    
                );

            // 2. Create body from _item:   list.Append(_item)
            MSAst.Expression body = ag.AddDebugInfo(
                Ast.Call(
                    AstGenerator.GetHelperMethod("ListAddForComprehension"),
                    list,
                    ag.TransformAsObject(_item)
                ),
                _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(ag, body);
            }

            return Ast.Block(
                initialize,
                body,
                list                        // result
            );
        }
Exemple #7
0
        internal override MSAst.Expression Transform(AstGenerator ag) {
            MSAst.Expression raiseExpression;
            if (_type == null && _value == null && _traceback == null) {
                raiseExpression = Ast.Call(
                    AstGenerator.GetHelperMethod("MakeRethrownException"),
                    ag.LocalContext
                );

                if (!ag._isEmittingFinally) {
                    raiseExpression = Ast.Block(
                        ag.UpdateLineUpdated(true),
                        raiseExpression
                    );
                }
            } else {
                raiseExpression = Ast.Call(
                    AstGenerator.GetHelperMethod("MakeException"),
                    ag.LocalContext,
                    ag.TransformOrConstantNull(_type, typeof(object)),
                    ag.TransformOrConstantNull(_value, typeof(object)),
                    ag.TransformOrConstantNull(_traceback, typeof(object))
                );
            }
            return ag.AddDebugInfo(
                Ast.Throw(raiseExpression),
                Span
            );
        }
Exemple #8
0
        internal override MSAst.Expression Transform(AstGenerator ag) {
            MSAst.MethodCallExpression call;

            if (_locals == null && _globals == null) {
                // exec code
                call = Ast.Call(
                    AstGenerator.GetHelperMethod("UnqualifiedExec"), 
                    AstUtils.CodeContext(), 
                    ag.TransformAsObject(_code)
                );
            } 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(
                    AstGenerator.GetHelperMethod("QualifiedExec"), 
                    AstUtils.CodeContext(), 
                    ag.TransformAsObject(_code), 
                    ag.TransformAndDynamicConvert(_globals, typeof(IAttributesCollection)), 
                    ag.TransformOrConstantNull(_locals, typeof(object))
                );
            }

            return ag.AddDebugInfo(call, Span);
        }
Exemple #9
0
        internal override MSAst.Expression Transform(AstGenerator ag) {
            MSAst.Expression result;

            if (_else != null) {
                result = ag.Transform(_else);
            } else {
                result = Ast.Empty();
            }

            // Now build from the inside out
            int i = _tests.Length;
            while (i-- > 0) {
                IfStatementTest ist = _tests[i];

                result = ag.AddDebugInfo(
                    Ast.Condition(
                        ag.TransformAndDynamicConvert(ist.Test, typeof(bool)), 
                        ag.Transform(ist.Body), 
                        result
                    ),
                    new SourceSpan(ist.Start, ist.Header)
                );
            }

            return result;
        }
Exemple #10
0
        internal override MSAst.Expression Transform(AstGenerator ag) {
            MSAst.Expression destination = ag.TransformAsObject(_dest);

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

                // Store destination in a temp, if we have one
                if (destination != null) {
                    MSAst.ParameterExpression temp = ag.GetTemporary("destination");

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

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

                    if (destination != null) {
                        mce = Ast.Call(
                            AstGenerator.GetHelperMethod(method + "WithDest"),
                            ag.LocalContext,
                            destination,
                            ag.TransformAsObject(current)
                        );
                    } else {
                        mce = Ast.Call(
                            AstGenerator.GetHelperMethod(method),
                            ag.LocalContext,
                            ag.TransformAsObject(current)
                        );
                    }

                    statements.Add(mce);
                }

                statements.Add(AstUtils.Empty());
                return ag.AddDebugInfo(Ast.Block(statements.ToArray()), Span);
            }
        }
Exemple #11
0
 internal override MSAst.Expression Transform(AstGenerator ag) {
     // 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(ag));
     }
     statements.Add(AstUtils.Empty());
     return ag.AddDebugInfo(MSAst.Expression.Block(statements), Span);
 }
 internal override MSAst.Expression Transform(AstGenerator ag) {
     if (ag.InFinally) {
         return null;
     } else if (ag.InLoop) {
         return ag.AddDebugInfo(MSAst.Expression.Continue(ag.ContinueLabel), Span);
     } else {
         return null;
     }
 }
Exemple #13
0
 internal override MSAst.Expression Transform(AstGenerator ag) {
     // Transform to series of individual del statements.
     MSAst.Expression[] statements = new MSAst.Expression[_expressions.Length + 1];
     for (int i = 0; i < _expressions.Length; i++) {
         statements[i] = _expressions[i].TransformDelete(ag);
     }
     statements[_expressions.Length] = AstUtils.Empty();
     return ag.AddDebugInfo(MSAst.Expression.Block(statements), Span);
 }
 internal override MSAst.Expression Transform(AstGenerator ag) {
     if (ag.InFinally) {
         ag.AddError("'continue' not supported inside 'finally' clause", Span);
         return null;
     } else if (ag.InLoop) {
         return ag.AddDebugInfo(MSAst.Expression.Continue(ag.ContinueLabel), Span);
     } else {
         ag.AddError("'continue' not properly in loop", Span);
         return null;
     }
 }
Exemple #15
0
 internal override MSAst.Expression Transform(AstGenerator ag) {
     // Transform to series of individual del statements.
     MSAst.Expression[] statements = new MSAst.Expression[_expressions.Length + 1];
     for (int i = 0; i < _expressions.Length; i++) {
         statements[i] = _expressions[i].TransformDelete(ag);
         if (statements[i] == null) {     
             throw PythonOps.SyntaxError(string.Format("can't delete {0}", _expressions[i].NodeName), ag.Context.SourceUnit, _expressions[i].Span, 1);
         }
     }
     statements[_expressions.Length] = MSAst.Expression.Empty();
     return ag.AddDebugInfo(MSAst.Expression.Block(statements), Span);
 }
Exemple #16
0
        internal override MSAst.Expression Transform(AstGenerator ag) {
            // If debugging is off, return empty statement
            if (ag.Optimize) {
                return ag.AddDebugInfo(AstUtils.Empty(), Span);
            }

            // Transform into:
            // if (_test) {
            // } else {
            //     RaiseAssertionError(_message);
            // }
            return ag.AddDebugInfo(
                AstUtils.Unless(                                 // if
                    ag.TransformAndDynamicConvert(_test, typeof(bool)), // _test
                    Ast.Call(                                           // else branch
                        AstGenerator.GetHelperMethod("RaiseAssertionError"),
                        ag.TransformOrConstantNull(_message, typeof(object))
                    )
                ),
                Span
            );
        }
Exemple #17
0
 internal override MSAst.Expression Transform(AstGenerator ag) {
     // Only the body is "in the loop" for the purposes of break/continue
     // The "else" clause is outside
     MSAst.LabelTarget breakLabel, continueLabel;
     MSAst.Expression body = ag.TransformLoopBody(_body, out breakLabel, out continueLabel);
     return AstUtils.While(
         ag.AddDebugInfo(
             ag.TransformAndDynamicConvert(_test, typeof(bool)),
             Header
         ),
         body, 
         ag.Transform(_else),
         breakLabel,
         continueLabel
     );
 }
Exemple #18
0
        internal override MSAst.Expression Transform(AstGenerator ag) {
            // Only the body is "in the loop" for the purposes of break/continue
            // The "else" clause is outside
            MSAst.LabelTarget breakLabel, continueLabel;

            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 ag.Transform(_else);
                    }
                }

                MSAst.Expression test = MSAst.Expression.Constant(true);
                MSAst.Expression res = AstUtils.While(
                    test,
                    ag.TransformLoopBody(_body, SourceLocation.Invalid, out breakLabel, out continueLabel),
                    ag.Transform(_else),
                    breakLabel,
                    continueLabel
                );

                if (_test.Start.Line != _body.Start.Line) {
                    res = ag.AddDebugInfo(res, _test.Span);
                }

                return res;
            }

            return AstUtils.While(
                ag.AddDebugInfo(
                    ag.TransformAndDynamicConvert(_test, typeof(bool)),
                    Header
                ),
                ag.TransformLoopBody(_body, _test.Start, out breakLabel, out continueLabel), 
                ag.Transform(_else),
                breakLabel,
                continueLabel
            );
        }
Exemple #19
0
        internal override MSAst.Expression Transform(AstGenerator ag, Type type) {
            // (yield z) becomes:
            // .comma (1) {
            //    .void ( .yield_statement (_expression) ),
            //    $gen.CheckThrowable() // <-- has return result from send            
            //  }

            return Ast.Block(
                ag.AddDebugInfo(
                    AstUtils.YieldReturn(
                        ag.GeneratorLabel,
                        AstUtils.Convert(ag.Transform(_expression), typeof(object))
                    ),
                    Span
                ),
                CreateCheckThrowExpression(ag, Span) // emits ($gen.CheckThrowable())
            );
        }
Exemple #20
0
 internal override MSAst.Expression Transform(AstGenerator ag) {
     MSAst.MethodCallExpression raiseExpression;
     if (_type == null && _value == null && _traceback == null) {
         raiseExpression = Ast.Call(
             AstGenerator.GetHelperMethod("MakeRethrownException"),
             AstUtils.CodeContext()
         );
     } else {
         raiseExpression = Ast.Call(
             AstGenerator.GetHelperMethod("MakeException"),
             AstUtils.CodeContext(),
             ag.TransformOrConstantNull(_type, typeof(object)),
             ag.TransformOrConstantNull(_value, typeof(object)),
             ag.TransformOrConstantNull(_traceback, typeof(object))
         );
     }
     return ag.AddDebugInfo(
         Ast.Throw(raiseExpression),
         Span
     );
 }
Exemple #21
0
 internal override MSAst.Expression TransformSet(AstGenerator ag, SourceSpan span, MSAst.Expression right, PythonOperationKind op) {
     if (op == PythonOperationKind.None) {
         return ag.AddDebugInfoAndVoid(
             ag.Set(
                 typeof(object),
                 _name,
                 ag.Transform(_target),
                 right
             ),
             span
         );
     } else {
         MSAst.ParameterExpression temp = ag.GetTemporary("inplace");
         return ag.AddDebugInfo(
             Ast.Block(
                 Ast.Assign(temp, ag.Transform(_target)),
                 SetMemberOperator(ag, right, op, temp),
                 AstUtils.Empty()
             ),
             Span.Start,
             span.End
         );
     }
 }
Exemple #22
0
 /// <summary>
 /// Surrounds the body of an except block w/ the appropriate code for maintaining the traceback.
 /// </summary>
 private static MSAst.Expression GetTracebackHeader(SourceSpan span, AstGenerator ag, MSAst.ParameterExpression exception, MSAst.Expression body) {
     // we are about to enter a except block.  We need to emit the line number update so we track
     // the line that the exception was thrown from.  We then need to build exc_info() so that
     // it's available.  Finally we clear the list of dynamic stack frames because they've all
     // been associated with this exception.
     return ag.AddDebugInfo(
         Ast.Block(
             // pass false so if we take another exception we'll add it to the frame list
             ag.TrackLines ? ag.GetLineNumberUpdateExpression(false) : MSAst.Expression.Empty(),    
             Ast.Call(
                 AstGenerator.GetHelperMethod("BuildExceptionInfo"),
                 AstUtils.CodeContext(),
                 exception
             ),
             body,
             Ast.Empty()
         ),
         span
     );
 }
        internal override MSAst.Expression Transform(AstGenerator ag) {
            Debug.Assert(_variable != null, "Shouldn't be called by lamda expression");

            ag.DisableInterpreter = true;
            MSAst.Expression function = TransformToFunctionExpression(ag);
            return ag.AddDebugInfo(AstUtils.Assign(_variable.Variable, function), new SourceSpan(Start, Header));
        }
Exemple #24
0
        internal static MSAst.Expression TransformForStatement(AstGenerator ag, MSAst.ParameterExpression enumerator,
                                                    Expression list, Expression left, MSAst.Expression body,
                                                    Statement else_, SourceSpan span, SourceLocation header,
                                                    MSAst.LabelTarget breakLabel, MSAst.LabelTarget continueLabel) {
            // enumerator = PythonOps.GetEnumeratorForIteration(list)
            MSAst.Expression init = Ast.Assign(
                    enumerator, 
                    ag.Operation(
                        typeof(IEnumerator),
                        PythonOperationKind.GetEnumeratorForIteration,
                        ag.TransformAsObject(list)
                    )
                );

            // while enumerator.MoveNext():
            //    left = enumerator.Current
            //    body
            // else:
            //    else
            MSAst.Expression ls = AstUtils.Loop(
                    ag.AddDebugInfo(Ast.Call(
                        enumerator,
                        typeof(IEnumerator).GetMethod("MoveNext")
                    ), left.Span),
                    null,
                    Ast.Block(
                        left.TransformSet(
                            ag,
                            SourceSpan.None,
                            Ast.Call(
                                enumerator,
                                typeof(IEnumerator).GetProperty("Current").GetGetMethod()
                            ),
                            PythonOperationKind.None
                        ),
                        body,
                        ag.UpdateLineNumber(list.Start.Line),
                        AstUtils.Empty()
                    ), 
                    ag.Transform(else_),
                    breakLabel, 
                    continueLabel
            );

            return Ast.Block(
                init,
                ls,
                AstUtils.Empty()
            );
        }
Exemple #25
0
        internal override MSAst.Expression Transform(AstGenerator ag) {
            // allocated all variables here so they won't be shared w/ other 
            // locals allocated during the body or except blocks.
            MSAst.ParameterExpression noNestedException = null;
            if (_finally != null) {
                noNestedException = ag.GetTemporary("$noException", typeof(bool));
            }

            MSAst.ParameterExpression lineUpdated = null;
            MSAst.ParameterExpression runElse = null;

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

            // don't allocate locals below here...
            MSAst.Expression body = ag.Transform(_body);
            MSAst.Expression @else = ag.Transform(_else);

            if (body == null) {
                return null;
            }

            MSAst.ParameterExpression exception;
            MSAst.Expression @catch = TransformHandlers(ag, out exception);
            MSAst.Expression result;

            // 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, Ast.Constant(true)),
                        // save existing line updated, we could choose to do this only for nested exception handlers.
                        ag.PushLineUpdated(false, lineUpdated),
                        AstUtils.Try(
                            ag.AddDebugInfo(Ast.Empty(), new SourceSpan(Span.Start, _header)),
                            body
                        ).Catch(exception,
                            Ast.Assign(runElse, Ast.Constant(false)),
                            @catch,
                            // restore existing line updated after exception handler completes
                            ag.PopLineUpdated(lineUpdated),
                            Ast.Default(body.Type)
                        ),
                        AstUtils.IfThen(runElse,
                            @else
                        ),
                        Ast.Empty()
                    );

            } else if (@catch != null) {        // no "else" clause
                //  try {
                //      <try body>
                //  } catch (Exception e) {
                //      ... catch handling ...
                //  }
                //
                result = AstUtils.Try(
                        ag.AddDebugInfo(Ast.Empty(), new SourceSpan(Span.Start, _header)),
                        // save existing line updated
                        ag.PushLineUpdated(false, lineUpdated),
                        body
                    ).Catch(exception,
                        @catch,
                        // restore existing line updated after exception handler completes
                        ag.PopLineUpdated(lineUpdated),
                        Ast.Default(body.Type)
                    );
            } else {
                result = body;
            }

            try {
                return AddFinally(ag, result, noNestedException);
            } finally {
                // free all locals here after the children nodes have been generated
                if (lineUpdated != null) {
                    ag.FreeTemp(lineUpdated);
                }
                if (runElse != null) {
                    ag.FreeTemp(@runElse);
                }
            }
        }
        internal MSAst.Expression TransformToFunctionExpression(AstGenerator ag) {
            string name;

            if (IsLambda) {
                name = "<lambda$" + Interlocked.Increment(ref _lambdaId) + ">";
            } else {
                name = SymbolTable.IdToString(_name);
            }

            // Create AST generator to generate the body with
            AstGenerator bodyGen = new AstGenerator(ag, name, IsGenerator, false);
            bodyGen.DisableInterpreter = true;

            // Transform the parameters.
            // Populate the list of the parameter names and defaults.
            List<MSAst.Expression> defaults = new List<MSAst.Expression>(0);
            List<MSAst.Expression> names = new List<MSAst.Expression>();
            TransformParameters(ag, bodyGen, defaults, names);

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

            // Create variables and references. Since references refer to
            // parameters, do this after parameters have been created.
            CreateVariables(bodyGen, statements);

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

            // 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(bodyGen, 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 = bodyGen.GetTemporary("$ex", typeof(Exception));
            }

            // Transform the body and add the resulting statements into the list
            TransformBody(bodyGen, statements);

            if (ag.DebugMode) {
                // add beginning and ending break points for the function.
                if (GetExpressionEnd(statements[statements.Count - 1]) != Body.End) {
                    statements.Add(ag.AddDebugInfo(Ast.Empty(), new SourceSpan(Body.End, Body.End)));
                }
            }

            MSAst.Expression body = Ast.Block(new ReadOnlyCollection<MSAst.Expression>(statements.ToArray()));

            // 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(
                            AstGenerator.GetHelperMethod("SaveCurrentException")
                        )
                    ),
                    body
                ).Finally(
                    Ast.Call(
                        AstGenerator.GetHelperMethod("RestoreCurrentException"), extracted
                    )
                );
                body = s;
            }

            body = bodyGen.WrapScopeStatements(body);
            bodyGen.Block.Body = bodyGen.AddReturnTarget(body);

            FunctionAttributes flags = ComputeFlags(_parameters);
            bool needsWrapperMethod = flags != FunctionAttributes.None;
            if (_canSetSysExcInfo) {
                flags |= FunctionAttributes.CanSetSysExcInfo;
            }

            MSAst.Expression code;
            if (IsGenerator) {
                code = bodyGen.Block.MakeGenerator(bodyGen.GeneratorLabel, GetGeneratorDelegateType(_parameters, needsWrapperMethod));
                flags |= FunctionAttributes.Generator;
            } else {
                code = bodyGen.Block.MakeLambda(GetDelegateType(_parameters, needsWrapperMethod));
            }

            MSAst.Expression ret = Ast.Call(
                null,                                                                                   // instance
                typeof(PythonOps).GetMethod("MakeFunction"),                                            // method
                new ReadOnlyCollection<MSAst.Expression>(
                    new [] {
                        AstUtils.CodeContext(),                                                         // 1. Emit CodeContext
                        Ast.Constant(name),                                                             // 2. FunctionName
                        code,                                                                           // 3. delegate
                        names.Count == 0 ?                                                              // 4. parameter names
                            Ast.Constant(null, typeof(string[])) :
                            (MSAst.Expression)Ast.NewArrayInit(typeof(string), names),
                        defaults.Count == 0 ?                                                           // 5. default values
                            Ast.Constant(null, typeof(object[])) :
                            (MSAst.Expression)Ast.NewArrayInit(typeof(object), defaults),                                   
                        Ast.Constant(flags),                                                            // 6. flags
                        Ast.Constant(ag.GetDocumentation(_body), typeof(string)),                       // 7. doc string or null
                        Ast.Constant(this.Start.Line),                                                  // 8. line number
                        Ast.Constant(_sourceUnit.Path, typeof(string))                                  // 9. filename
                    }
                )
            );

            ret = ag.AddDecorators(ret, _decorators);

            return ret;
        }
 internal override MSAst.Expression TransformDelete(AstGenerator ag) {
     MSAst.Expression[] statements = new MSAst.Expression[_items.Length + 1];
     for (int i = 0; i < _items.Length; i++) {
         statements[i] = _items[i].TransformDelete(ag);
     }
     statements[_items.Length] = AstUtils.Empty();
     return ag.AddDebugInfo(Ast.Block(statements), Span);
 }
        internal override MSAst.Expression Transform(AstGenerator ag) {            
            if (_names == _star) {
                // from a[.b] import *
                return ag.AddDebugInfo(
                    Ast.Call(
                        AstGenerator.GetHelperMethod("ImportStar"), 
                        AstUtils.CodeContext(), 
                        Ast.Constant(_root.MakeString()), 
                        Ast.Constant(GetLevel())
                    ),
                    Span
                );
            } else {
                // from a[.b] import x [as xx], [ y [ as yy] ] [ , ... ]

                List<MSAst.Expression> statements = new List<MSAst.Expression>();
                MSAst.ParameterExpression module = ag.GetTemporary("module");

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

                // module = PythonOps.ImportWithNames(<context>, _root, make_array(_names))
                statements.Add(
                    ag.AddDebugInfo(
                        AstUtils.Assign(
                            module, 
                            Ast.Call(
                                AstGenerator.GetHelperMethod("ImportWithNames"),
                                AstUtils.CodeContext(),
                                Ast.Constant(_root.MakeString()),
                                Ast.NewArrayInit(typeof(string), names),
                                Ast.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(
                        ag.AddDebugInfo(
                            AstUtils.Assign(
                                _variables[i].Variable, 
                                Ast.Call(
                                    AstGenerator.GetHelperMethod("ImportFrom"),
                                    AstUtils.CodeContext(),
                                    module,
                                    names[i]
                                )
                            ),
                            Span
                        )
                    );
                }

                statements.Add(Ast.Empty());
                return ag.AddDebugInfo(Ast.Block(statements.ToArray()), Span);
            }
        }
        internal override MSAst.Expression TransformSet(AstGenerator ag, 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 = ag.GetTemporary("unpacking");

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

            // 3. Call GetEnumeratorValues on the right side (stored in temp)
            MSAst.Expression enumeratorValues = Ast.Call(
                AstGenerator.GetHelperMethod("GetEnumeratorValues"),    // method
                // arguments
                ag.LocalContext,
                right_temp,
                AstUtils.Constant(_items.Length)
            );

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

            // 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 = ag.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(
                    ag,
                    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 = ag.AddDebugInfo(Ast.Block(sets.ToReadOnlyCollection()), leftSpan);

            // 10. Free the temps
            ag.FreeTemp(array_temp);
            ag.FreeTemp(right_temp);

            // 11. Return the suite statement (block)
            return ag.AddDebugInfo(Ast.Block(assignStmt1, assignStmt2, itemSet, AstUtils.Empty()), totalSpan);
        }
Exemple #30
0
        internal override MSAst.Expression Transform(AstGenerator ag) {
            string className = SymbolTable.IdToString(_name);
            AstGenerator builder = new AstGenerator(ag, className, false, "class " + className);

            // we always need to create a nested context for class defs
            builder.CreateNestedContext();

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

            // Create the body
            MSAst.Expression bodyStmt = builder.Transform(_body);
            MSAst.Expression modStmt = ag.Globals.Assign(ag.Globals.GetVariable(_modVariable), ag.Globals.GetVariable(_modNameVariable));

            string doc = ag.GetDocumentation(_body);
            if (doc != null) {
                init.Add(
                    ag.Globals.Assign(
                        ag.Globals.GetVariable(_docVariable),
                        AstUtils.Constant(doc)
                    )
                );
            }

            bodyStmt = builder.WrapScopeStatements(
                Ast.Block(
                    init.Count == 0 ?
                        AstGenerator.EmptyBlock :
                        Ast.Block(new ReadOnlyCollection<MSAst.Expression>(init)),
                    modStmt,
                    bodyStmt,
                    builder.LocalContext    // return value
                )
            );

            MSAst.LambdaExpression lambda = Ast.Lambda(
                typeof(Func<CodeContext>),
                builder.MakeBody(bodyStmt, true, false),
                builder.Name + "$" + _classId++,
                builder.Parameters
            );

            MSAst.Expression classDef = Ast.Call(
                AstGenerator.GetHelperMethod("MakeClass"),
                lambda,
                ag.LocalContext,
                AstUtils.Constant(SymbolTable.IdToString(_name)),
                Ast.NewArrayInit(
                    typeof(object),
                    ag.TransformAndConvert(_bases, typeof(object))
                ),
                AstUtils.Constant(FindSelfNames())
            );

            classDef = ag.AddDecorators(classDef, _decorators);

            return ag.AddDebugInfo(ag.Globals.Assign(ag.Globals.GetVariable(_variable), classDef), new SourceSpan(Start, Header));
        }