1
0
forked from VimPlug/jedi

further removals of unused code, also changes evaluate, now.

This commit is contained in:
David Halter
2013-02-07 17:39:40 +01:00
parent d2ab0fe862
commit d6a5a3e0e7
3 changed files with 94 additions and 113 deletions

View File

@@ -580,52 +580,52 @@ def follow_call_list(call_list, follow_array=False):
return loop return loop
if pr.Array.is_type(call_list, pr.Array.TUPLE, pr.Array.DICT): if pr.Array.is_type(call_list, pr.Array.TUPLE, pr.Array.DICT):
raise NotImplementedError('TODO')
# Tuples can stand just alone without any braces. These would be # Tuples can stand just alone without any braces. These would be
# recognized as separate calls, but actually are a tuple. # recognized as separate calls, but actually are a tuple.
result = follow_call(call_list) result = follow_call(call_list)
else: else:
result = [] result = []
for calls in call_list: calls_iterator = iter(call_list)
calls_iterator = iter(calls) for call in calls_iterator:
for call in calls_iterator: if pr.Array.is_type(call, pr.Array.NOARRAY):
if pr.Array.is_type(call, pr.Array.NOARRAY): result += follow_call_list(call, follow_array=True)
result += follow_call_list(call, follow_array=True) elif isinstance(call, pr.ListComprehension):
elif isinstance(call, pr.ListComprehension): loop = evaluate_list_comprehension(call)
loop = evaluate_list_comprehension(call) stmt = copy.copy(call.stmt)
stmt = copy.copy(call.stmt) stmt.parent = loop
stmt.parent = loop # create a for loop which does the same as list
# create a for loop which does the same as list # comprehensions
# comprehensions result += follow_statement(stmt)
result += follow_statement(stmt) else:
else: if isinstance(call, (pr.Lambda)):
if isinstance(call, (pr.Lambda)): result.append(er.Function(call))
result.append(er.Function(call)) # With things like params, these can also be functions...
# With things like params, these can also be functions... elif isinstance(call, (er.Function, er.Class, er.Instance,
elif isinstance(call, (er.Function, er.Class, er.Instance, dynamic.ArrayInstance)):
dynamic.ArrayInstance)): 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, unicode)):
elif not isinstance(call, (str, unicode)): if str(call.name) == 'if':
if str(call.name) == 'if': # Ternary operators.
# Ternary operators. while True:
while True: try:
try: call = next(calls_iterator)
call = next(calls_iterator) except StopIteration:
except StopIteration: break
try:
if str(call.name) == 'else':
break break
try: except AttributeError:
if str(call.name) == 'else': pass
break continue
except AttributeError: result += follow_call(call)
pass elif call == '*':
continue if [r for r in result if isinstance(r, er.Array)
result += follow_call(call) or isinstance(r, er.Instance)
elif call == '*': and str(r.name) == 'str']:
if [r for r in result if isinstance(r, er.Array) # if it is an iterable, ignore * operations
or isinstance(r, er.Instance) next(calls_iterator)
and str(r.name) == 'str']:
# if it is an iterable, ignore * operations
next(calls_iterator)
if follow_array and isinstance(call_list, pr.Array): if follow_array and isinstance(call_list, pr.Array):
# call_list can also be a two dimensional array # call_list can also be a two dimensional array

View File

@@ -497,7 +497,6 @@ class Execution(Executable):
new_param = copy.copy(param) new_param = copy.copy(param)
if parent_stmt is not None: if parent_stmt is not None:
new_param.parent = parent_stmt new_param.parent = parent_stmt
new_param._assignment_calls_calculated = True
new_param._assignment_calls = calls new_param._assignment_calls = calls
new_param.is_generated = True new_param.is_generated = True
name = copy.copy(param.get_name()) name = copy.copy(param.get_name())

View File

@@ -45,33 +45,11 @@ class Base(object):
return isinstance(self, cls) return isinstance(self, cls)
class Simple(Base): class BasePosition(Base):
"""
The super class for Scope, Import, Name and Statement. Every object in
the parser tree inherits from this class.
"""
__slots__ = ('parent', 'module', '_start_pos', 'use_as_parent', '_end_pos')
def __init__(self, module, start_pos, end_pos=(None, None)): def __init__(self, module, start_pos, end_pos=(None, None)):
self.module = module
self._start_pos = start_pos self._start_pos = start_pos
self._end_pos = end_pos self._end_pos = end_pos
self.parent = None
# use this attribute if parent should be something else than self.
self.use_as_parent = self
self.module = module
@Python3Method
def get_parent_until(self, classes=(), reverse=False,
include_current=True):
""" Takes always the parent, until one class (not a Class) """
if type(classes) not in (tuple, list):
classes = (classes,)
scope = self if include_current else self.parent
while scope.parent is not None:
if classes and reverse != scope.isinstance(*classes):
break
scope = scope.parent
return scope
@property @property
def start_pos(self): def start_pos(self):
@@ -91,6 +69,33 @@ class Simple(Base):
def end_pos(self, value): def end_pos(self, value):
self._end_pos = value self._end_pos = value
class Simple(BasePosition):
"""
The super class for Scope, Import, Name and Statement. Every object in
the parser tree inherits from this class.
"""
__slots__ = ('parent', 'module', '_start_pos', 'use_as_parent', '_end_pos')
def __init__(self, module, start_pos, end_pos=(None, None)):
super(Simple, self).__init__(module, start_pos, end_pos)
self.parent = None
# use this attribute if parent should be something else than self.
self.use_as_parent = self
@Python3Method
def get_parent_until(self, classes=(), reverse=False,
include_current=True):
""" Takes always the parent, until one class (not a Class) """
if type(classes) not in (tuple, list):
classes = (classes,)
scope = self if include_current else self.parent
while scope.parent is not None:
if classes and reverse != scope.isinstance(*classes):
break
scope = scope.parent
return scope
def __repr__(self): def __repr__(self):
code = self.get_code().replace('\n', ' ') code = self.get_code().replace('\n', ' ')
return "<%s: %s@%s>" % \ return "<%s: %s@%s>" % \
@@ -658,8 +663,7 @@ class Statement(Simple):
:type start_pos: tuple(int, int) :type start_pos: tuple(int, int)
""" """
__slots__ = ('used_funcs', 'code', 'token_list', 'used_vars', __slots__ = ('used_funcs', 'code', 'token_list', 'used_vars',
'set_vars', '_assignment_calls', '_assignment_details', 'set_vars', '_assignment_calls', '_assignment_details')
'_assignment_calls_calculated')
def __init__(self, module, code, set_vars, used_funcs, used_vars, def __init__(self, module, code, set_vars, used_funcs, used_vars,
token_list, start_pos, end_pos, parent=None): token_list, start_pos, end_pos, parent=None):
@@ -678,7 +682,6 @@ class Statement(Simple):
self._assignment_calls = None self._assignment_calls = None
self._assignment_details = None self._assignment_details = None
# this is important for other scripts # this is important for other scripts
self._assignment_calls_calculated = False
def _remove_executions_from_set_vars(self, set_vars): def _remove_executions_from_set_vars(self, set_vars):
""" """
@@ -735,6 +738,13 @@ class Statement(Simple):
return str(self.token_list[0]) == "global" return str(self.token_list[0]) == "global"
def get_assignment_calls(self): def get_assignment_calls(self):
if self._assignment_calls is None:
# TODO check
result = self._parse_statement()
self._assignment_calls = result
return self._assignment_calls
def _parse_statement(self):
""" """
This is not done in the main parser, because it might be slow and This is not done in the main parser, because it might be slow and
most of the statements won't need this data anyway. This is something most of the statements won't need this data anyway. This is something
@@ -743,12 +753,6 @@ class Statement(Simple):
This is not really nice written, sorry for that. If you plan to replace This is not really nice written, sorry for that. If you plan to replace
it and make it nicer, that would be cool :-) it and make it nicer, that would be cool :-)
""" """
if self._assignment_calls_calculated:
return self._assignment_calls
brackets = {'(': Array.TUPLE, '[': Array.LIST, '{': Array.SET}
closing_brackets = [')', '}', ']']
def parse_array(token_iterator, array_type, start_pos, add_el=None): def parse_array(token_iterator, array_type, start_pos, add_el=None):
arr = Array(start_pos, array_type) arr = Array(start_pos, array_type)
if add_el is not None: if add_el is not None:
@@ -797,13 +801,13 @@ class Statement(Simple):
statement.parent = self.parent statement.parent = self.parent
return statement return statement
# initializations
self._assignment_details = [] self._assignment_details = []
result = [] result = []
is_chain = False is_chain = False
close_brackets = False close_brackets = False
brackets = {'(': Array.TUPLE, '[': Array.LIST, '{': Array.SET}
is_call = lambda: result and type(result[-1]) == Call closing_brackets = [')', '}', ']']
is_call_or_close = lambda: is_call() or close_brackets
token_iterator = enumerate(self.token_list) token_iterator = enumerate(self.token_list)
for i, tok_temp in token_iterator: for i, tok_temp in token_iterator:
@@ -842,24 +846,26 @@ class Statement(Simple):
elif token_type == tokenize.NUMBER: elif token_type == tokenize.NUMBER:
c_type = Call.NUMBER c_type = Call.NUMBER
call = Call(tok, c_type, start_pos, parent=result) call = Call(self.module, tok, c_type, start_pos, self)
if is_chain: if is_chain:
result[-1].set_next(call) result[-1].set_next(call)
is_chain = False
close_brackets = False
else: else:
result.append(call) result.append(call)
is_chain = False
close_brackets = False
elif tok in brackets.keys(): elif tok in brackets.keys():
arr = parse_array(token_iterator, brackets[tok], start_pos) arr = parse_array(token_iterator, brackets[tok], start_pos)
if is_call_or_close(): if type(result[-1]) == Call or close_brackets:
result[-1].add_execution(arr) result[-1].add_execution(arr)
else: else:
result.append(arr) result.append(arr)
close_brackets = True close_brackets = True
elif tok == '.': elif tok == '.':
close_brackets = False
if result and isinstance(result[-1], Call): if result and isinstance(result[-1], Call):
is_chain = True is_chain = True
elif tok == ',': # implies a tuple elif tok == ',': # implies a tuple
close_brackets = False
# rewrite `result`, because now the whole thing is a tuple # rewrite `result`, because now the whole thing is a tuple
add_el = parse_statement(iter(result), start_pos) add_el = parse_statement(iter(result), start_pos)
arr = parse_array(token_iterator, Array.TUPLE, start_pos, arr = parse_array(token_iterator, Array.TUPLE, start_pos,
@@ -870,9 +876,6 @@ class Statement(Simple):
if tok != '\n': if tok != '\n':
result.append(tok) result.append(tok)
# TODO check
self._assignment_calls_calculated = True
self._assignment_calls = result
return result return result
@@ -908,7 +911,7 @@ class Param(Statement):
return n[0] return n[0]
class Call(Base): class Call(BasePosition):
""" """
`Call` contains a call, e.g. `foo.bar` and owns the executions of those `Call` contains a call, e.g. `foo.bar` and owns the executions of those
calls, which are `Array`s. calls, which are `Array`s.
@@ -917,45 +920,24 @@ class Call(Base):
NUMBER = 2 NUMBER = 2
STRING = 3 STRING = 3
def __init__(self, name, type, start_pos, parent_stmt=None, parent=None): def __init__(self, module, name, type, start_pos, parent=None):
super(Call, self).__init__(module, start_pos)
self.name = name self.name = name
# parent is not the oposite of next. The parent of c: a = [b.c] would # parent is not the oposite of next. The parent of c: a = [b.c] would
# be an array. # be an array.
self.parent = parent self.parent = parent
self.type = type self.type = type
self.start_pos = start_pos
self.next = None self.next = None
self.execution = None self.execution = None
self._parent_stmt = parent_stmt
@property
def start_pos(self):
offset = self.parent_stmt.module.line_offset
return offset + self._start_pos[0], self._start_pos[1]
@start_pos.setter
def start_pos(self, value):
self._start_pos = value
@property
def parent_stmt(self):
if self._parent_stmt is not None:
return self._parent_stmt
elif self.parent:
return self.parent.parent_stmt
else:
return None
@parent_stmt.setter
def parent_stmt(self, value):
self._parent_stmt = value
def set_next(self, call): def set_next(self, call):
""" Adds another part of the statement""" """ Adds another part of the statement"""
self.next = call if self.next is not None:
call.parent = self.parent self.next.set_next(call)
return call else:
self.next = call
call.parent = self.parent
def add_execution(self, call): def add_execution(self, call):
""" """