Add basic yield from type inference. References #647.

This commit is contained in:
Dave Halter
2016-07-09 02:33:16 +02:00
parent 5280f567f9
commit e0cb1346e1
4 changed files with 43 additions and 6 deletions

View File

@@ -676,6 +676,9 @@ class FunctionExecution(Executed):
check = flow_analysis.break_check(self._evaluator, self, r)
if check is flow_analysis.UNREACHABLE:
debug.dbg('Return unreachable: %s', r)
else:
if check_yields:
types |= iterable.unite(self._eval_yield(r))
else:
types |= self._evaluator.eval_element(r.children[1])
if check is flow_analysis.REACHABLE:
@@ -683,6 +686,16 @@ class FunctionExecution(Executed):
break
return types
def _eval_yield(self, yield_expr):
element = yield_expr.children[1]
if element.type == 'yield_arg':
# It must be a yield from.
yield_from_types = self._evaluator.eval_element(element.children[1])
for result in iterable.py__iter__(self._evaluator, yield_from_types, element):
yield result
else:
yield self._evaluator.eval_element(element)
# TODO add execution_recursion_decorator?!
def get_yield_types(self):
yields = self.yields
@@ -716,7 +729,8 @@ class FunctionExecution(Executed):
if for_stmt is None:
# No for_stmt, just normal yields.
for yield_ in yields:
yield evaluator.eval_element(yield_.children[1])
for result in self._eval_yield(yield_):
yield result
else:
input_node = for_stmt.get_input_node()
for_types = evaluator.eval_element(input_node)
@@ -725,7 +739,8 @@ class FunctionExecution(Executed):
dct = {str(for_stmt.children[1]): index_types}
evaluator.predefined_if_name_dict_dict[for_stmt] = dct
for yield_in_same_for_stmt in yields:
yield evaluator.eval_element(yield_in_same_for_stmt.children[1])
for result in self._eval_yield(yield_in_same_for_stmt):
yield result
del evaluator.predefined_if_name_dict_dict[for_stmt]
def names_dicts(self, search_global):

View File

@@ -175,3 +175,25 @@ gen().send()
#?
gen()()
# -----------------
# yield from
# -----------------
# python >= 3.3
def yield_from():
yield from iter([1])
#? int()
next(yield_from())
def yield_from_multiple():
yield from iter([1])
yield str()
x, y = yield_from_multiple()
#? int()
x
#? str()
y

View File

@@ -49,7 +49,7 @@ class Employee:
# The typing library is not installable for Python 2.6, therefore ignore the
# following tests.
# python > 2.6
# python >= 2.7
from typing import List
x = [] # type: List[Employee]

View File

@@ -240,8 +240,8 @@ def skip_python_version(line):
'==': 'eq',
'<=': 'le',
'>=': 'ge',
'<': 'gk',
'>': 'lt',
'<': 'lt',
'>': 'gt',
}
# check for python minimal version number
match = re.match(r" *# *python *([<>]=?|==) *(\d+(?:\.\d+)?)$", line)