IronPython.Compiler.Ast.FunctionDefinition.CreateFunctionLambda C# (CSharp) Метод

CreateFunctionLambda() приватный Метод

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.
private CreateFunctionLambda ( ) : Microsoft.Scripting.Ast.LightLambdaExpression
Результат Microsoft.Scripting.Ast.LightLambdaExpression
        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);

            // 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
            );
        }