Beispiel #1
0
        public AstPythonFunction(PythonAst ast, IPythonModule declModule, IPythonType declType, FunctionDefinition def, string doc) {
            DeclaringModule = declModule;
            DeclaringType = declType;

            Name = def.Name;
            Documentation = doc;

            foreach (var dec in (def.Decorators?.Decorators).MaybeEnumerate().OfType<NameExpression>()) {
                if (dec.Name == "classmethod") {
                    IsClassMethod = true;
                } else if (dec.Name == "staticmethod") {
                    IsStatic = true;
                }
            }

            _overloads = new List<AstPythonFunctionOverload> {
                new AstPythonFunctionOverload(Documentation, "", MakeParameters(ast, def), MakeReturns(def))
            };
        }
Beispiel #2
0
 public override bool Walk(FunctionDefinition node) {
     _names.Add(node.Name);
     return base.Walk(node);
 }
Beispiel #3
0
 private void PushFunction(FunctionDefinition function) {
     if (_functions == null) {
         _functions = new Stack<FunctionDefinition>();
     }
     _functions.Push(function);
 }
Beispiel #4
0
        // Helpers for parsing lambda expressions. 
        // Usage
        //   FunctionDefinition f = ParseLambdaHelperStart(string);
        //   Expression expr = ParseXYZ();
        //   return ParseLambdaHelperEnd(f, expr);
        private FunctionDefinition ParseLambdaHelperStart(out List<string> commaWhiteSpace, out bool ateTerminator) {
            var start = GetStart();
            Parameter[] parameters;

            parameters = ParseVarArgsList(TokenKind.Colon, out commaWhiteSpace, out ateTerminator);
            var mid = GetEnd();

            FunctionDefinition func = new FunctionDefinition(null, parameters ?? new Parameter[0]); // new Parameter[0] for error handling of incomplete lambda
            func.HeaderIndex = mid;
            func.StartIndex = start;

            // Push the lambda function on the stack so that it's available for any yield expressions to mark it as a generator.
            PushFunction(func);

            return func;
        }
        public ExtractMethodResult GetExtractionResult(ExtractMethodRequest info) {
            bool isStaticMethod = false, isClassMethod = false;
            var parameters = new List<Parameter>();
            string selfParam = null;
            if (info.TargetScope is ClassDefinition) {
                var fromScope = _scopes[_scopes.Length - 1] as FunctionDefinition;
                Debug.Assert(fromScope != null);  // we don't allow extracting from classes, so we have to be coming from a function
                if (fromScope != null) {
                    if (fromScope.Decorators != null) {
                        foreach (var decorator in fromScope.Decorators.Decorators) {
                            NameExpression name = decorator as NameExpression;
                            if (name != null) {
                                if (name.Name == "staticmethod") {
                                    isStaticMethod = true;
                                } else if (name.Name == "classmethod") {
                                    isClassMethod = true;
                                }
                            }
                        }
                    }

                    if (!isStaticMethod) {
                        if (fromScope.Parameters.Count > 0) {
                            selfParam = fromScope.Parameters[0].Name;
                            parameters.Add(new Parameter(selfParam, ParameterKind.Normal));
                        }
                    }
                }
            }

            foreach (var param in info.Parameters) {
                var newParam = new Parameter(param, ParameterKind.Normal);
                if (parameters.Count > 0) {
                    newParam.AddPreceedingWhiteSpace(_ast, " ");
                }
                parameters.Add(newParam);
            }

            // include any non-closed over parameters as well...
            foreach (var input in _inputVars) {
                var variableScope = input.Scope;
                var parentScope = info.TargetScope;

                // are these variables a child of the target scope so we can close over them?
                while (parentScope != null && parentScope != variableScope) {
                    parentScope = parentScope.Parent;
                }

                if (parentScope == null && input.Name != selfParam) {
                    // we can either close over or pass these in as parameters, add them to the list
                    var newParam = new Parameter(input.Name, ParameterKind.Normal);
                    if (parameters.Count > 0) {
                        newParam.AddPreceedingWhiteSpace(_ast, " ");
                    }
                    parameters.Add(newParam);
                }
            }

            var body = _target.GetBody(_ast);
            var isCoroutine = IsCoroutine(body);

            // reset leading indentation to single newline + indentation, this
            // strips out any proceeding comments which we don't extract
            var leading = _newline + body.GetIndentationLevel(_ast);
            body.SetLeadingWhiteSpace(_ast, leading);

            if (_outputVars.Count > 0) {
                // need to add a return statement
                Expression retValue;
                Expression[] names = new Expression[_outputVars.Count];
                int outputIndex = 0;
                foreach (var name in _outputVars) {
                    var nameExpr = new NameExpression(name.Name);
                    nameExpr.AddPreceedingWhiteSpace(_ast, " ");
                    names[outputIndex++] = nameExpr;
                }
                var tuple = new TupleExpression(false, names);
                tuple.RoundTripHasNoParenthesis(_ast);
                retValue = tuple;

                var retStmt = new ReturnStatement(retValue);
                retStmt.SetLeadingWhiteSpace(_ast, leading);

                body = new SuiteStatement(
                    new Statement[] { 
                        body,
                        retStmt
                    }
                );
            } else {
                // we need a SuiteStatement to give us our colon
                body = new SuiteStatement(new Statement[] { body });
            }

            DecoratorStatement decorators = null;
            if (isStaticMethod) {
                decorators = new DecoratorStatement(new[] { new NameExpression("staticmethod") });
            } else if (isClassMethod) {
                decorators = new DecoratorStatement(new[] { new NameExpression("classmethod") });
            }

            var res = new FunctionDefinition(new NameExpression(info.Name), parameters.ToArray(), body, decorators);
            res.IsCoroutine = isCoroutine;
            
            StringBuilder newCall = new StringBuilder();
            newCall.Append(_target.IndentationLevel);
            var method = res.ToCodeString(_ast);

            // fix up indentation...
            for (int curScope = 0; curScope < _scopes.Length; curScope++) {
                if (_scopes[curScope] == info.TargetScope) {
                    // this is our target indentation level.
                    var indentationLevel = _scopes[curScope].Body.GetIndentationLevel(_ast);
                    var lines = method.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None);
                    int minWhiteSpace = Int32.MaxValue;
                    for (int curLine = decorators == null ? 1 : 2; curLine < lines.Length; curLine++) {
                        var line = lines[curLine];

                        for (int i = 0; i < line.Length; i++) {
                            if (!Char.IsWhiteSpace(line[i])) {
                                minWhiteSpace = Math.Min(minWhiteSpace, i);
                                break;
                            }
                        }
                    }

                    StringBuilder newLines = new StringBuilder();
                    newLines.Append(indentationLevel);
                    newLines.Append(lines[0]);
                    if (decorators != null) {
                        newLines.Append(_newline);
                        newLines.Append(indentationLevel);
                        newLines.Append(lines[1]);
                    }

                    // don't include a bunch of blank lines...
                    int endLine = lines.Length - 1;
                    for (; endLine >= 0 && String.IsNullOrWhiteSpace(lines[endLine]); endLine--) {
                    }

                    newLines.Append(_newline);
                    for (int curLine = decorators == null ? 1 : 2; curLine <= endLine; curLine++) {
                        var line = lines[curLine];

                        newLines.Append(indentationLevel);
                        if (_insertTabs) {
                            newLines.Append('\t');
                        } else {
                            newLines.Append(' ', _indentSize);
                        }

                        if (line.Length > minWhiteSpace) {
                            newLines.Append(line, minWhiteSpace, line.Length - minWhiteSpace);
                        }
                        newLines.Append(_newline);
                    }
                    newLines.Append(_newline);
                    method = newLines.ToString();
                    break;
                }
            }

            string comma;
            if (_outputVars.Count > 0) {
                comma = "";
                foreach (var outputVar in _outputVars) {
                    newCall.Append(comma);
                    newCall.Append(outputVar.Name);
                    comma = ", ";
                }
                newCall.Append(" = ");
            } else if (_target.ContainsReturn) {
                newCall.Append("return ");
            }

            if (isCoroutine) {
                newCall.Append("await ");
            }

            if (info.TargetScope is ClassDefinition) {
                var fromScope = _scopes[_scopes.Length - 1] as FunctionDefinition;
                Debug.Assert(fromScope != null);  // we don't allow extracting from classes, so we have to be coming from a function

                if (isStaticMethod) {
                    newCall.Append(info.TargetScope.Name);
                    newCall.Append('.');
                } else if (fromScope != null && fromScope.Parameters.Count > 0) {
                    newCall.Append(fromScope.Parameters[0].Name);
                    newCall.Append('.');
                }
            }

            newCall.Append(info.Name);
            newCall.Append('(');

            comma = "";
            foreach (var param in parameters) {
                if (param.Name != selfParam) {
                    newCall.Append(comma);
                    newCall.Append(param.Name);
                    comma = ", ";
                }
            }

            newCall.Append(')');

            return new ExtractMethodResult(
                method,
                newCall.ToString()
            );
        }
        public override bool Walk(FunctionDefinition node) {
            if (node.IsCoroutine) {
                AddSpan(Tuple.Create("", new Span(node.StartIndex, 5)), PredefinedClassificationTypeNames.Keyword);
            }

            Debug.Assert(_head != null);
            _head.Functions.Add(node.NameExpression.Name);
            node.NameExpression.Walk(this);
            BeginScope();
            return base.Walk(node);
        }
Beispiel #7
0
        // FunctionDefinition
        public override bool Walk(FunctionDefinition node) {
            node._nameVariable = _globalScope.EnsureGlobalVariable("__name__");
            
            // Name is defined in the enclosing context
            if (!node.IsLambda) {
                node.Variable = DefineName(node.Name);
                node.AddVariableReference(_globalScope, _bindRefs, Reference(node.Name));
            }
            
            // process the default arg values and annotations in the outer
            // context
            foreach (Parameter p in node.Parameters) {
                if (p.DefaultValue != null) {
                    p.DefaultValue.Walk(this);
                }
                if (p.Annotation != null) {
                    p.Annotation.Walk(this);
                }
            }
            // process the decorators in the outer context
            if (node.Decorators != null) {
                foreach (Expression dec in node.Decorators.Decorators) {
                    if (dec != null) {
                        dec.Walk(this);
                    }
                }
            }
            // process the return annotation in the outer context
            if (node.ReturnAnnotation != null) {
                node.ReturnAnnotation.Walk(this);
            }

            PushScope(node);

            foreach (Parameter p in node.Parameters) {
                p.Walk(_parameter);
            }

            if (node.Body != null) {
                node.Body.Walk(this);
            }
            return false;
        }
Beispiel #8
0
 public override bool Walk(FunctionDefinition node) {
     var function = AddFunction(node, _curUnit);
     if (function != null) {
         _analysisStack.Push(_curUnit);
         _curUnit = function.AnalysisUnit;
         Debug.Assert(_scope.EnumerateTowardsGlobal.Contains(function.AnalysisUnit.Scope.OuterScope));
         _scope = function.AnalysisUnit.Scope;
         return true;
     }
     return false;
 }
Beispiel #9
0
 private static IEnumerable<IPythonType> MakeReturns(FunctionDefinition def) {
     yield break;
 }
Beispiel #10
0
 private static IEnumerable<IParameterInfo> MakeParameters(PythonAst ast, FunctionDefinition def) {
     foreach (var p in def.Parameters) {
         yield return new AstPythonParameterInfo(ast, p);
     }
 }
Beispiel #11
0
 internal void AddOverload(PythonAst ast, FunctionDefinition def) {
     _overloads.Add(new AstPythonFunctionOverload(def.Documentation, "", MakeParameters(ast, def), MakeReturns(def)));
 }
Beispiel #12
0
 public LambdaExpression(FunctionDefinition function) {
     _function = function;
 }
Beispiel #13
0
 public override void PostWalk(FunctionDefinition node) {
     _scopes.Add(node);
     _allWrites.Add(node.GetVariableReference(_root));
     _allWrittenVariables.Add(node.Variable);
     base.PostWalk(node);
 }
Beispiel #14
0
 public override void PostWalk(FunctionDefinition node) {
     _scopes.Add(node);
     base.PostWalk(node);
 }
Beispiel #15
0
            public override bool Walk(FunctionDefinition node) {
                if (!node.IsLambda) {
                    _define.WalkName(node.NameExpression, node.GetVariableReference(_root));
                }

                bool oldInLoop = _inLoop;
                _inLoop = false;
                var res = base.Walk(node);
                _inLoop = oldInLoop;
                return res;
            }
 // FunctionDefinition
 public override void PostWalk(FunctionDefinition node)
 {
     Debug.Assert(_currentScope == node);
     PopScope();
 }
Beispiel #17
0
        internal static FunctionInfo AddFunction(FunctionDefinition node, AnalysisUnit outerUnit, InterpreterScope prevScope) {
            InterpreterScope scope;
            if (!prevScope.TryGetNodeScope(node, out scope)) {
                if (node.Body == null || node.Name == null) {
                    return null;
                }

                var func = new FunctionInfo(node, outerUnit, prevScope);
                var unit = func.AnalysisUnit;
                scope = unit.Scope;

                prevScope.Children.Add(scope);
                prevScope.AddNodeScope(node, scope);

                if (!node.IsLambda && node.Name != "<genexpr>") {
                    // lambdas don't have their names published

                    var funcVar = prevScope.AddLocatedVariable(node.Name, node.NameExpression, unit);
                    // Decorated functions don't have their type set yet
                    if (node.Decorators == null) {
                        funcVar.AddTypes(unit, func.SelfSet);
                    }
                }

                unit.Enqueue();
            }
            return scope.AnalysisValue as FunctionInfo;
        }
Beispiel #18
0
            public override void PostWalk(FunctionDefinition node) {
                int start = node.GetStart(_ast).Line;
                int end = node.Body.GetEnd(_ast).Line + 1;
                if (_lineNumber < start || _lineNumber >= end) {
                    return;
                }

                string funcName = node.Name;
                if (_name.Length == 0 && funcName != _expectedFuncName) {
                    // The innermost function name must match the one that we've got from the code object.
                    // If it doesn't, the source code that we're parsing is out of sync with the running program,
                    // and cannot be used to compute the fully qualified name.
                    throw new InvalidDataException();
                }

                for (var classDef = node.Parent as ClassDefinition; classDef != null; classDef = classDef.Parent as ClassDefinition) {
                    funcName = classDef.Name + "." + funcName;
                }

                if (_name.Length != 0) {
                    _name.Append(" in ");
                }

                _name.Append(funcName);
            }
Beispiel #19
0
        public override bool Walk(FunctionDefinition node) {
            var newScope = WalkScope(node);
            CurScope.Children.Add(newScope);

            return false;
        }
Beispiel #20
0
        private void GetFunctionDescription(FunctionDefinition def, Action<string, VSOBDESCRIPTIONSECTION, IVsNavInfo> addDescription) {
            addDescription(ScopeNode.Name, VSOBDESCRIPTIONSECTION.OBDS_NAME, null);
            addDescription("(", VSOBDESCRIPTIONSECTION.OBDS_MISC, null);

            for (int i = 0; i < def.Parameters.Count; i++) {
                if (i != 0) {
                    addDescription(", ", VSOBDESCRIPTIONSECTION.OBDS_MISC, null);
                }

                var curParam = def.Parameters[i];

                string name = curParam.Name;
                if (curParam.IsDictionary) {
                    name = "**" + name;
                } else if (curParam.IsList) {
                    name = "*" + curParam.Name;
                }

                if (curParam.DefaultValue != null) {
                    // TODO: Support all possible expressions for default values, we should
                    // probably have a PythonAst walker for expressions or we should add ToCodeString()
                    // onto Python ASTs so they can round trip
                    ConstantExpression defaultValue = curParam.DefaultValue as ConstantExpression;
                    if (defaultValue != null) {
                        // FIXME: Use python repr
                        name = name + " = " + defaultValue.GetConstantRepr(def.GlobalParent.LanguageVersion);
                    }
                }

                addDescription(name, VSOBDESCRIPTIONSECTION.OBDS_PARAM, null);
            }
            addDescription(")\n", VSOBDESCRIPTIONSECTION.OBDS_MISC, null);
        }
Beispiel #21
0
 // FunctionDefinition
 public override void PostWalk(FunctionDefinition node) {
     Debug.Assert(_currentScope == node);
     PopScope();
 }
Beispiel #22
0
 public FunctionScopeNode(FunctionDefinition func) {
     _func = func;
 }
 public override void PostWalk(FunctionDefinition node) {
     EndScope(false);
     Debug.Assert(_head != null);
     base.PostWalk(node);
 }
Beispiel #24
0
 public override bool Walk(FunctionDefinition node) {
     var existing = GetInScope(node.Name) as AstPythonFunction;
     if (existing == null) {
         var m = _scope.Peek();
         if (m != null) {
             m[node.Name] = new AstPythonFunction(_ast, _module, CurrentClass, node, GetDoc(node.Body as SuiteStatement));
         }
     } else {
         existing.AddOverload(_ast, node);
     }
     // Do not recurse into functions
     return false;
 }
Beispiel #25
0
        // funcdef: [decorators] 'def' NAME parameters ':' suite
        // parameters: '(' [varargslist] ')'
        // this gets called with "def" as the look-ahead
        private FunctionDefinition ParseFuncDef(bool isCoroutine) {
            string preWhitespace = null, afterAsyncWhitespace = null;

            var start = isCoroutine ? GetStart() : 0;
            if (isCoroutine) {
                preWhitespace = _tokenWhiteSpace;
            }
            Eat(TokenKind.KeywordDef);
            
            if (isCoroutine) {
                afterAsyncWhitespace = _tokenWhiteSpace;
            } else {
                preWhitespace = _tokenWhiteSpace;
                start = GetStart();
            }

            var name = ReadName();
            var nameExpr = MakeName(name);
            nameExpr.SetLoc(GetStart(), GetEnd());
            string nameWhiteSpace = _tokenWhiteSpace;

            bool ateLeftParen = name.HasName && Eat(TokenKind.LeftParenthesis);
            string parenWhiteSpace = _tokenWhiteSpace;

            var lStart = GetStart();
            var lEnd = GetEnd();
            int grouping = _tokenizer.GroupingLevel;

            List<string> commaWhiteSpace = null;
            bool ateTerminator = false;
            Parameter[] parameters = ateLeftParen ? ParseVarArgsList(TokenKind.RightParenthesis, out commaWhiteSpace, out ateTerminator, true) : null;
            string closeParenWhiteSpace = _tokenWhiteSpace;
            FunctionDefinition ret;
            if (parameters == null) {
                // error in parameters
                ret = new FunctionDefinition(nameExpr, new Parameter[0]);
                ret.IsCoroutine = isCoroutine;
                if (_verbatim) {
                    AddVerbatimName(name, ret);
                    AddPreceedingWhiteSpace(ret, preWhitespace);
                    if (afterAsyncWhitespace != null) {
                        GetNodeAttributes(ret)[FunctionDefinition.WhitespaceAfterAsync] = afterAsyncWhitespace;
                    }
                    AddSecondPreceedingWhiteSpace(ret, nameWhiteSpace);
                    AddThirdPreceedingWhiteSpace(ret, parenWhiteSpace);
                    AddFourthPreceedingWhiteSpace(ret, closeParenWhiteSpace);
                    if (!ateTerminator) {
                        AddErrorMissingCloseGrouping(ret);
                    }
                    if (!ateLeftParen) {
                        AddErrorIsIncompleteNode(ret);
                    }
                }
                ret.SetLoc(start, lEnd);
                return ret;
            }

            string arrowWhiteSpace = null;
            Expression returnAnnotation = null;
            if (MaybeEat(TokenKind.Arrow)) {
                arrowWhiteSpace = _tokenWhiteSpace;
                returnAnnotation = ParseExpression();
            }

            var rStart = GetStart();
            var rEnd = GetEnd();

            ret = new FunctionDefinition(nameExpr, parameters);
            AddVerbatimName(name, ret);

            PushFunction(ret);

            // set IsCoroutine before parsing the body to enable use of 'await'
            ret.IsCoroutine = isCoroutine;

            Statement body = ParseClassOrFuncBody();
            FunctionDefinition ret2 = PopFunction();
            System.Diagnostics.Debug.Assert(ret == ret2);

            ret.SetBody(body);
            ret.ReturnAnnotation = returnAnnotation;
            ret.HeaderIndex = rEnd;
            if (_verbatim) {
                AddPreceedingWhiteSpace(ret, preWhitespace);
                if (afterAsyncWhitespace != null) {
                    GetNodeAttributes(ret)[FunctionDefinition.WhitespaceAfterAsync] = afterAsyncWhitespace;
                }
                AddSecondPreceedingWhiteSpace(ret, nameWhiteSpace);
                AddThirdPreceedingWhiteSpace(ret, parenWhiteSpace);
                AddFourthPreceedingWhiteSpace(ret, closeParenWhiteSpace);
                AddListWhiteSpace(ret, commaWhiteSpace.ToArray());
                if (arrowWhiteSpace != null) {
                    AddFifthPreceedingWhiteSpace(ret, arrowWhiteSpace);
                }
                if (!ateTerminator) {
                    AddErrorMissingCloseGrouping(ret);
                }
            }
            ret.SetLoc(start, body.EndIndex);

            return ret;
        }        
Beispiel #26
0
 public override void PostWalk(FunctionDefinition node) {
     _scopes.RemoveAt(_scopes.Count - 1);
     base.PostWalk(node);
 }
Beispiel #27
0
        private Expression ParseLambdaHelperEnd(FunctionDefinition func, Expression expr, string whitespace, string colonWhiteSpace, List<string> commaWhiteSpace, bool ateTerminator) {
            // Pep 342 in Python 2.5 allows Yield Expressions, which can occur inside a Lambda body. 
            // In this case, the lambda is a generator and will yield it's final result instead of just return it.
            Statement body;
            if (func.IsGenerator) {
                YieldExpression y = new YieldExpression(expr);
                y.SetLoc(expr.IndexSpan);
                body = new ExpressionStatement(y);
            } else {
                body = new ReturnStatement(expr);
            }
            body.SetLoc(expr.StartIndex, expr.EndIndex);

            FunctionDefinition func2 = PopFunction();
            System.Diagnostics.Debug.Assert(func == func2);

            func.SetBody(body);
            func.EndIndex = GetEnd();

            LambdaExpression ret = new LambdaExpression(func);
            func.SetLoc(func.IndexSpan);
            ret.SetLoc(func.IndexSpan);
            if (_verbatim) {
                AddPreceedingWhiteSpace(ret, whitespace);
                AddSecondPreceedingWhiteSpace(ret, colonWhiteSpace);
                AddListWhiteSpace(ret, commaWhiteSpace.ToArray());
                if (!ateTerminator) {
                    AddErrorIsIncompleteNode(ret);
                }
            }
            return ret;
        }
Beispiel #28
0
 public override void PostWalk(FunctionDefinition node) {
     if (node.Body != null && node.Name != null) {
         Debug.Assert(_scope.EnumerateTowardsGlobal.Contains(_curUnit.Scope.OuterScope));
         _scope = _curUnit.Scope.OuterScope;
         _curUnit = _analysisStack.Pop();
         Debug.Assert(_scope.EnumerateTowardsGlobal.Contains(_curUnit.Scope));
     }
 }
Beispiel #29
0
 private static ImageListKind GetImageListKind(FunctionDefinition funcDef) {
     ImageListKind imageKind = ImageListKind.Method;
     if (funcDef.Decorators != null && funcDef.Decorators.Decorators.Count == 1) {
         foreach (var decorator in funcDef.Decorators.Decorators) {
             NameExpression nameExpr = decorator as NameExpression;
             if (nameExpr != null) {
                 if (nameExpr.Name == "property") {
                     imageKind = ImageListKind.Property;
                     break;
                 } else if (nameExpr.Name == "staticmethod") {
                     imageKind = ImageListKind.StaticMethod;
                     break;
                 } else if (nameExpr.Name == "classmethod") {
                     imageKind = ImageListKind.ClassMethod;
                     break;
                 }
             }
         }
     }
     return imageKind;
 }
Beispiel #30
0
 internal FunctionInfo AddFunction(FunctionDefinition node, AnalysisUnit outerUnit) {
     return AddFunction(node, outerUnit, _scope);
 }
            public override bool Walk(FunctionDefinition node) {
                CommitByDefault = true;
                if (node.Parameters != null) {
                    CanComplete = false;
                    foreach (var p in node.Parameters) {
                        p.Walk(this);
                    }
                }
                if (node.Decorators != null) {
                    node.Decorators.Walk(this);
                }
                if (node.ReturnAnnotation != null) {
                    CanComplete = true;
                    node.ReturnAnnotation.Walk(this);
                }
                if (node.Body != null && !(node.Body is ErrorStatement)) {
                    CanComplete = node.IsLambda;
                    node.Body.Walk(this);
                }

                return false;
            }
Beispiel #32
0
 public LambdaExpression(FunctionDefinition function)
 {
     _function = function;
 }