Implicit tuples as a separate class.

This commit is contained in:
Dave Halter
2014-11-06 18:24:55 +01:00
parent 8200b68549
commit 460d959988
2 changed files with 36 additions and 17 deletions
+2 -5
View File
@@ -183,7 +183,7 @@ class Evaluator(object):
return types return types
elif pr.is_node(element, 'testlist_star_expr', 'testlist'): elif pr.is_node(element, 'testlist_star_expr', 'testlist'):
# The implicit tuple in statements. # The implicit tuple in statements.
return [iterable.Array(self, element, pr.Array.TUPLE)] return [iterable.ImplicitTuple(self, element)]
elif pr.is_node(element, 'not_test') or pr.is_node(element, 'factor'): elif pr.is_node(element, 'not_test') or pr.is_node(element, 'factor'):
types = self.eval_element(element.children[-1]) types = self.eval_element(element.children[-1])
for operator in element.children[:-1]: for operator in element.children[:-1]:
@@ -206,15 +206,12 @@ class Evaluator(object):
elif isinstance(atom, pr.Literal): elif isinstance(atom, pr.Literal):
return [compiled.create(self, atom.eval())] return [compiled.create(self, atom.eval())]
else: else:
mapping = {'(': pr.Array.TUPLE,
'[': pr.Array.LIST,
'{': pr.Array.DICT}
c = atom.children c = atom.children
# Parentheses without commas are not tuples. # Parentheses without commas are not tuples.
if c[0] == '(' and (not pr.is_node(c[1], 'testlist_comp') if c[0] == '(' and (not pr.is_node(c[1], 'testlist_comp')
or c[1].children[1] != ','): or c[1].children[1] != ','):
return self.eval_element(c[1]) return self.eval_element(c[1])
return [iterable.Array(self, c[1], mapping[c[0]])] return [iterable.Array(self, atom)]
def _eval_trailer(self, types, trailer): def _eval_trailer(self, types, trailer):
trailer_op, node = trailer.children[:2] trailer_op, node = trailer.children[:2]
+34 -12
View File
@@ -124,10 +124,14 @@ class Array(IterableWrapper):
Used as a mirror to pr.Array, if needed. It defines some getter Used as a mirror to pr.Array, if needed. It defines some getter
methods which are important in this module. methods which are important in this module.
""" """
def __init__(self, evaluator, array_node, type): mapping = {'(': pr.Array.TUPLE,
'[': pr.Array.LIST,
'{': pr.Array.DICT}
def __init__(self, evaluator, atom):
self._evaluator = evaluator self._evaluator = evaluator
self._array_node = array_node self._atom = atom
self.type = type self.type = Array.mapping[atom.children[0]]
@property @property
def name(self): def name(self):
@@ -204,7 +208,7 @@ class Array(IterableWrapper):
if name not in ['start_pos', 'get_only_subelement', 'parent', if name not in ['start_pos', 'get_only_subelement', 'parent',
'get_parent_until', 'items']: 'get_parent_until', 'items']:
raise AttributeError('Strange access on %s: %s.' % (self, name)) raise AttributeError('Strange access on %s: %s.' % (self, name))
return getattr(self._array_node, name) return getattr(self._atom, name)
def _values(self): def _values(self):
if self.type == pr.Array.DICT: if self.type == pr.Array.DICT:
@@ -213,11 +217,16 @@ class Array(IterableWrapper):
return self._items() return self._items()
def _items(self): def _items(self):
if pr.is_node(self._array_node, 'testlist_comp', 'testlist_star_expr', 'testlist'): c = self._atom.children
return self._array_node.children[::2] array_node = c[1]
elif pr.is_node(self._array_node, 'dictorsetmaker'): if array_node in (']', '}', ')'):
return [] # Direct closing bracket, doesn't contain items.
if pr.is_node(array_node, 'testlist_comp', 'testlist_star_expr', 'testlist'):
return array_node.children[::2]
elif pr.is_node(array_node, 'dictorsetmaker'):
kv = [] kv = []
iterator = iter(self._array_node.children) iterator = iter(array_node.children)
for key in iterator: for key in iterator:
op = next(iterator, None) op = next(iterator, None)
if op is None or op == ',': if op is None or op == ',':
@@ -229,18 +238,30 @@ class Array(IterableWrapper):
raise NotImplementedError('dict/set comprehensions') raise NotImplementedError('dict/set comprehensions')
return kv return kv
else: else:
return [self._array_node] return [array_node]
def __iter__(self): def __iter__(self):
return iter(self._items()) return iter(self._items())
def __repr__(self): def __repr__(self):
return "<e%s of %s>" % (type(self).__name__, self._array_node) return "<e%s of %s>" % (type(self).__name__, self._atom)
class ImplicitTuple(Array):
def __init__(self, evaluator, testlist):
self._evaluator = evaluator
self.type = pr.Array.TUPLE
self._testlist = testlist
def _items(self):
return self._testlist.children[::2]
class FakeSequence(Array): class FakeSequence(Array):
def __init__(self, evaluator, sequence_values, type): def __init__(self, evaluator, sequence_values, type):
super(FakeSequence, self).__init__(evaluator, None, type) # Intentionally don't call the parent __init__.
self._evaluator = evaluator
self.type = type
self._sequence_values = sequence_values self._sequence_values = sequence_values
def _items(self): def _items(self):
@@ -253,7 +274,8 @@ class FakeSequence(Array):
class FakeDict(Array): class FakeDict(Array):
def __init__(self, evaluator, dct): def __init__(self, evaluator, dct):
super(FakeDict, self).__init__(evaluator, None, pr.Array.DICT) self._evaluator = evaluator
self.type = pr.Array.DICT
self._dct = dct self._dct = dct
def get_exact_index_types(self, index): def get_exact_index_types(self, index):