forked from VimPlug/jedi
Get lambdas mostly working.
This commit is contained in:
@@ -176,6 +176,8 @@ class Evaluator(object):
|
|||||||
elif isinstance(element, pr.Keyword):
|
elif isinstance(element, pr.Keyword):
|
||||||
# For False/True/None
|
# For False/True/None
|
||||||
return [compiled.builtin.get_by_name(element.value)]
|
return [compiled.builtin.get_by_name(element.value)]
|
||||||
|
elif isinstance(element, pr.Lambda):
|
||||||
|
return [er.LambdaWrapper(self, element)]
|
||||||
elif element.type == 'power':
|
elif element.type == 'power':
|
||||||
types = self._eval_atom(element.children[0])
|
types = self._eval_atom(element.children[0])
|
||||||
for trailer in element.children[1:]:
|
for trailer in element.children[1:]:
|
||||||
|
|||||||
@@ -74,9 +74,12 @@ class NameFinder(object):
|
|||||||
except KeyError:
|
except KeyError:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
if isinstance(scope, pr.CompFor):
|
if isinstance(scope, (pr.CompFor, pr.Lambda)):
|
||||||
return names
|
return names
|
||||||
names = pr.filter_after_position(names, position)
|
|
||||||
|
if not (isinstance(scope, er.FunctionExecution)
|
||||||
|
and isinstance(scope.base, er.LambdaWrapper)):
|
||||||
|
names = pr.filter_after_position(names, position)
|
||||||
names = [name for name in names if name.is_definition()]
|
names = [name for name in names if name.is_definition()]
|
||||||
|
|
||||||
# Only the names defined in the last position are valid definitions.
|
# Only the names defined in the last position are valid definitions.
|
||||||
@@ -539,6 +542,7 @@ def get_names_of_scope(evaluator, scope, position=None, star_search=True, includ
|
|||||||
if isinstance(scope, pr.SubModule) and scope.parent or not scope.is_scope():
|
if isinstance(scope, pr.SubModule) and scope.parent or not scope.is_scope():
|
||||||
scope = scope.parent
|
scope = scope.parent
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# `pr.Class` is used, because the parent is never `Class`.
|
# `pr.Class` is used, because the parent is never `Class`.
|
||||||
# Ignore the Flows, because the classes and functions care for that.
|
# Ignore the Flows, because the classes and functions care for that.
|
||||||
# InstanceElement of Class is ignored, if it is not the start scope.
|
# InstanceElement of Class is ignored, if it is not the start scope.
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ class Executed(pr.Base):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def get_parent_until(self, *args, **kwargs):
|
def get_parent_until(self, *args, **kwargs):
|
||||||
return self.base.get_parent_until(*args, **kwargs)
|
return pr.Base.get_parent_until(self, *args, **kwargs)
|
||||||
|
|
||||||
@common.safe_property
|
@common.safe_property
|
||||||
def parent(self):
|
def parent(self):
|
||||||
@@ -512,7 +512,7 @@ class Function(use_metaclass(CachedMetaClass, Wrapper)):
|
|||||||
|
|
||||||
debug.dbg('decorator end %s', f)
|
debug.dbg('decorator end %s', f)
|
||||||
|
|
||||||
if isinstance(f, pr.Function):
|
if isinstance(f, (pr.Function, pr.Lambda)):
|
||||||
return self
|
return self
|
||||||
return f
|
return f
|
||||||
|
|
||||||
@@ -542,6 +542,10 @@ class Function(use_metaclass(CachedMetaClass, Wrapper)):
|
|||||||
return "<e%s of %s%s>" % (type(self).__name__, self.base_func, dec)
|
return "<e%s of %s%s>" % (type(self).__name__, self.base_func, dec)
|
||||||
|
|
||||||
|
|
||||||
|
class LambdaWrapper(Function):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class LazyDict(object):
|
class LazyDict(object):
|
||||||
def __init__(self, old_dct, copy_func):
|
def __init__(self, old_dct, copy_func):
|
||||||
self._copy_func = copy_func
|
self._copy_func = copy_func
|
||||||
@@ -588,6 +592,9 @@ class FunctionExecution(Executed):
|
|||||||
# inserted params, not in the actual execution of the function.
|
# inserted params, not in the actual execution of the function.
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
if isinstance(func, LambdaWrapper):
|
||||||
|
return self._evaluator.eval_element(self.children[-1])
|
||||||
|
|
||||||
if check_yields:
|
if check_yields:
|
||||||
types = []
|
types = []
|
||||||
returns = self.yields
|
returns = self.yields
|
||||||
|
|||||||
@@ -102,6 +102,7 @@ class Parser(object):
|
|||||||
'try_stmt': pt.TryStmt,
|
'try_stmt': pt.TryStmt,
|
||||||
'comp_for': pt.CompFor,
|
'comp_for': pt.CompFor,
|
||||||
'decorator': pt.Decorator,
|
'decorator': pt.Decorator,
|
||||||
|
'lambdef': pt.Lambda,
|
||||||
}
|
}
|
||||||
|
|
||||||
self.global_names = []
|
self.global_names = []
|
||||||
|
|||||||
@@ -762,6 +762,30 @@ class Class(ClassOrFunc):
|
|||||||
yield self, filter_after_position(self.get_defined_names(), position)
|
yield self, filter_after_position(self.get_defined_names(), position)
|
||||||
|
|
||||||
|
|
||||||
|
def _create_params(function, lst):
|
||||||
|
if not lst:
|
||||||
|
return []
|
||||||
|
if is_node(lst[0], 'typedargslist', 'varargslist'):
|
||||||
|
params = []
|
||||||
|
iterator = iter(lst[0].children)
|
||||||
|
for n in iterator:
|
||||||
|
stars = 0
|
||||||
|
if n in ('*', '**'):
|
||||||
|
stars = len(n.value)
|
||||||
|
n = next(iterator)
|
||||||
|
|
||||||
|
op = next(iterator, None)
|
||||||
|
if op == '=':
|
||||||
|
default = next(iterator)
|
||||||
|
next(iterator, None)
|
||||||
|
else:
|
||||||
|
default = None
|
||||||
|
params.append(Param(n, function, default, stars))
|
||||||
|
return params
|
||||||
|
else:
|
||||||
|
return [Param(lst[0], function)]
|
||||||
|
|
||||||
|
|
||||||
class Function(ClassOrFunc):
|
class Function(ClassOrFunc):
|
||||||
"""
|
"""
|
||||||
Used to store the parsed contents of a python function.
|
Used to store the parsed contents of a python function.
|
||||||
@@ -778,36 +802,13 @@ class Function(ClassOrFunc):
|
|||||||
def __init__(self, children):
|
def __init__(self, children):
|
||||||
super(Function, self).__init__(children)
|
super(Function, self).__init__(children)
|
||||||
self.listeners = set() # not used here, but in evaluation.
|
self.listeners = set() # not used here, but in evaluation.
|
||||||
self.params = self._params()
|
lst = self.children[2].children[1:-1] # After `def foo`
|
||||||
|
self.params = _create_params(self, lst)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
return self.children[1] # First token after `def`
|
return self.children[1] # First token after `def`
|
||||||
|
|
||||||
def _params(self):
|
|
||||||
node = self.children[2].children[1:-1] # After `def foo`
|
|
||||||
if not node:
|
|
||||||
return []
|
|
||||||
if is_node(node[0], 'typedargslist'):
|
|
||||||
params = []
|
|
||||||
iterator = iter(node[0].children)
|
|
||||||
for n in iterator:
|
|
||||||
stars = 0
|
|
||||||
if n in ('*', '**'):
|
|
||||||
stars = len(n.value)
|
|
||||||
n = next(iterator)
|
|
||||||
|
|
||||||
op = next(iterator, None)
|
|
||||||
if op == '=':
|
|
||||||
default = next(iterator)
|
|
||||||
next(iterator, None)
|
|
||||||
else:
|
|
||||||
default = None
|
|
||||||
params.append(Param(n, self, default, stars))
|
|
||||||
return params
|
|
||||||
else:
|
|
||||||
return [Param(node[0], self)]
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def yields(self):
|
def yields(self):
|
||||||
# TODO This is incorrect, yields are also possible in a statement.
|
# TODO This is incorrect, yields are also possible in a statement.
|
||||||
@@ -871,13 +872,25 @@ class Function(ClassOrFunc):
|
|||||||
|
|
||||||
|
|
||||||
class Lambda(Function):
|
class Lambda(Function):
|
||||||
def __init__(self, module, params, start_pos, parent):
|
"""
|
||||||
super(Lambda, self).__init__(module, None, params, start_pos, None)
|
Lambdas are basically trimmed functions, so give it the same interface.
|
||||||
self.parent = parent
|
"""
|
||||||
|
def __init__(self, children):
|
||||||
|
super(Function, self).__init__(children)
|
||||||
|
self.listeners = set() # not used here, but in evaluation.
|
||||||
|
lst = self.children[1:-2] # After `def foo`
|
||||||
|
self.params = _create_params(self, lst)
|
||||||
|
self.names_dict = dict((str(param.name), [param.name])
|
||||||
|
for param in self.params)
|
||||||
|
|
||||||
|
def is_generator(self):
|
||||||
|
return False
|
||||||
|
|
||||||
|
def yields(self):
|
||||||
|
return []
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<%s @%s (%s-%s)>" % (type(self).__name__, self.start_pos[0],
|
return "<%s@%s>" % (self.__class__.__name__, self.start_pos)
|
||||||
self.start_pos[1], self.end_pos[1])
|
|
||||||
|
|
||||||
|
|
||||||
class Flow(Simple):
|
class Flow(Simple):
|
||||||
|
|||||||
Reference in New Issue
Block a user