forked from VimPlug/jedi
working list comprehensions with tests.
This commit is contained in:
20
evaluate.py
20
evaluate.py
@@ -856,6 +856,8 @@ def get_names_for_scope(scope, position=None, star_search=True,
|
|||||||
"""
|
"""
|
||||||
start_scope = scope
|
start_scope = scope
|
||||||
in_scope = scope
|
in_scope = scope
|
||||||
|
if isinstance(start_scope, parsing.ForFlow) and start_scope.is_list_comp:
|
||||||
|
yield start_scope, start_scope.get_set_vars(is_internal_call=True)
|
||||||
while scope:
|
while scope:
|
||||||
# `parsing.Class` is used, because the parent is never `Class`.
|
# `parsing.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.
|
||||||
@@ -1192,18 +1194,24 @@ def follow_call_list(call_list):
|
|||||||
for call in calls_iterator:
|
for call in calls_iterator:
|
||||||
if parsing.Array.is_type(call, parsing.Array.NOARRAY):
|
if parsing.Array.is_type(call, parsing.Array.NOARRAY):
|
||||||
result += follow_call_list(call)
|
result += follow_call_list(call)
|
||||||
|
elif isinstance(call, parsing.ListComprehension):
|
||||||
|
stmt = call.stmt
|
||||||
|
# create a for loop which does the same as list
|
||||||
|
# comprehensions
|
||||||
|
loop = parsing.ForFlow([call.input], stmt.start_pos,
|
||||||
|
call.middle, True)
|
||||||
|
loop.parent = weakref.ref(stmt.parent())
|
||||||
|
stmt = copy.copy(stmt)
|
||||||
|
stmt.parent = lambda: loop
|
||||||
|
result += follow_statement(stmt)
|
||||||
else:
|
else:
|
||||||
# With things like params, these can also be functions...
|
|
||||||
if isinstance(call, (Function, Class, Instance,
|
if isinstance(call, (Function, Class, Instance,
|
||||||
dynamic.ArrayInstance)):
|
dynamic.ArrayInstance)):
|
||||||
|
# With things like params, these can also be functions...
|
||||||
result.append(call)
|
result.append(call)
|
||||||
# The string tokens are just operations (+, -, etc.)
|
# The string tokens are just operations (+, -, etc.)
|
||||||
elif not isinstance(call, str):
|
elif not isinstance(call, str):
|
||||||
if str(call.name) == 'for':
|
if str(call.name) == 'if':
|
||||||
# list comprehensions
|
|
||||||
print '\n\ndini mueter', call_list
|
|
||||||
return []
|
|
||||||
elif str(call.name) == 'if':
|
|
||||||
# Ternary operators.
|
# Ternary operators.
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
|
|||||||
29
parsing.py
29
parsing.py
@@ -479,10 +479,11 @@ class ForFlow(Flow):
|
|||||||
"""
|
"""
|
||||||
Used for the for loop, because there are two statement parts.
|
Used for the for loop, because there are two statement parts.
|
||||||
"""
|
"""
|
||||||
def __init__(self, command, inits, start_pos, set_stmt):
|
def __init__(self, inits, start_pos, set_stmt, is_list_comp=False):
|
||||||
super(ForFlow, self).__init__(command, inits, start_pos,
|
super(ForFlow, self).__init__('for', inits, start_pos,
|
||||||
set_stmt.used_vars)
|
set_stmt.used_vars)
|
||||||
self.set_stmt = set_stmt
|
self.set_stmt = set_stmt
|
||||||
|
self.is_list_comp = is_list_comp
|
||||||
|
|
||||||
|
|
||||||
class Import(Simple):
|
class Import(Simple):
|
||||||
@@ -664,6 +665,9 @@ class Statement(Simple):
|
|||||||
tok_iter = enumerate(self.token_list)
|
tok_iter = enumerate(self.token_list)
|
||||||
for i, tok_temp in tok_iter:
|
for i, tok_temp in tok_iter:
|
||||||
#print 'tok', tok_temp, result
|
#print 'tok', tok_temp, result
|
||||||
|
if isinstance(tok_temp, ListComprehension):
|
||||||
|
result.add_to_current_field(tok_temp)
|
||||||
|
continue
|
||||||
try:
|
try:
|
||||||
token_type, tok, start_pos = tok_temp
|
token_type, tok, start_pos = tok_temp
|
||||||
except TypeError:
|
except TypeError:
|
||||||
@@ -1006,14 +1010,14 @@ class Name(Simple):
|
|||||||
|
|
||||||
class ListComprehension(object):
|
class ListComprehension(object):
|
||||||
""" Helper class for list comprehensions """
|
""" Helper class for list comprehensions """
|
||||||
def __init__(self, tok_list, middle, input):
|
def __init__(self, stmt, middle, input):
|
||||||
self.tok_list = tok_list
|
self.stmt = stmt
|
||||||
self.middle = middle
|
self.middle = middle
|
||||||
self.input = input
|
self.input = input
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<%s: %s for in %s>" % \
|
return "<%s: %s for %s in %s>" % \
|
||||||
(self.__class__.__name__, self.tok_list, self.input)
|
(self.__class__.__name__, self.stmt, self.middle, self.input)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1322,7 +1326,9 @@ class PyFuzzyParser(object):
|
|||||||
(tok, self.start_pos[0]))
|
(tok, self.start_pos[0]))
|
||||||
continue
|
continue
|
||||||
other_level = 0
|
other_level = 0
|
||||||
for i, (d1, tok, d2) in enumerate(reversed(tok_list)):
|
for i, tok in enumerate(reversed(tok_list)):
|
||||||
|
if not isinstance(tok, Name):
|
||||||
|
tok = tok[1]
|
||||||
if tok in closing_brackets:
|
if tok in closing_brackets:
|
||||||
other_level -= 1
|
other_level -= 1
|
||||||
elif tok in opening_brackets:
|
elif tok in opening_brackets:
|
||||||
@@ -1333,7 +1339,11 @@ class PyFuzzyParser(object):
|
|||||||
i = 0 # could not detect brackets -> nested list comp
|
i = 0 # could not detect brackets -> nested list comp
|
||||||
|
|
||||||
tok_list, toks = tok_list[:-i], tok_list[-i:-1]
|
tok_list, toks = tok_list[:-i], tok_list[-i:-1]
|
||||||
tok_list.append(ListComprehension(toks, middle, in_clause))
|
st = Statement('', [], [], [], \
|
||||||
|
toks, first_pos, self.end_pos)
|
||||||
|
for s in [st, middle, in_clause]:
|
||||||
|
s.parent = weakref.ref(self.scope)
|
||||||
|
tok_list.append(ListComprehension(st, middle, in_clause))
|
||||||
print tok_list
|
print tok_list
|
||||||
elif tok in ['print', 'exec']:
|
elif tok in ['print', 'exec']:
|
||||||
# TODO they should be reinstated, since the goal of the
|
# TODO they should be reinstated, since the goal of the
|
||||||
@@ -1399,7 +1409,6 @@ class PyFuzzyParser(object):
|
|||||||
|
|
||||||
if list_comp:
|
if list_comp:
|
||||||
self.gen.push_back(self._current_full)
|
self.gen.push_back(self._current_full)
|
||||||
|
|
||||||
return stmt, tok
|
return stmt, tok
|
||||||
|
|
||||||
def next(self):
|
def next(self):
|
||||||
@@ -1522,7 +1531,7 @@ class PyFuzzyParser(object):
|
|||||||
if tok == 'in':
|
if tok == 'in':
|
||||||
statement, tok = self._parse_statement()
|
statement, tok = self._parse_statement()
|
||||||
if tok == ':':
|
if tok == ':':
|
||||||
f = ForFlow('for', [statement], first_pos,
|
f = ForFlow([statement], first_pos,
|
||||||
set_stmt)
|
set_stmt)
|
||||||
self.scope = self.scope.add_statement(f)
|
self.scope = self.scope.add_statement(f)
|
||||||
|
|
||||||
|
|||||||
@@ -56,11 +56,24 @@ for i in range(10):
|
|||||||
# list comprehensions
|
# list comprehensions
|
||||||
# -----------------
|
# -----------------
|
||||||
|
|
||||||
a = ['' for abc in [1]]
|
# basics:
|
||||||
|
|
||||||
|
a = ['' for a in [1]]
|
||||||
#? str()
|
#? str()
|
||||||
a[0]
|
a[0]
|
||||||
|
|
||||||
|
a = [a for a in [1]]
|
||||||
|
#? int()
|
||||||
|
a[0]
|
||||||
|
|
||||||
|
a = [a for a,b in [(1,'')]]
|
||||||
|
#? int()
|
||||||
|
a[0]
|
||||||
|
|
||||||
|
arr = [1,'']
|
||||||
|
a = [a for a in arr]
|
||||||
|
#? int() str()
|
||||||
|
a[0]
|
||||||
|
|
||||||
# -----------------
|
# -----------------
|
||||||
# ternary operator
|
# ternary operator
|
||||||
|
|||||||
Reference in New Issue
Block a user