validators.escape: support arrays in multiple assignment.

This commit is contained in:
whitequark 2015-12-14 16:31:03 +08:00
parent 1860364778
commit e755e1ba9e
2 changed files with 26 additions and 20 deletions

View File

@ -32,8 +32,8 @@ class Region:
self.range.end_pos >= other.range.end_pos self.range.end_pos >= other.range.end_pos
def intersects(self, other): def intersects(self, other):
assert self.range.source_buffer == other.range.source_buffer
assert self.range assert self.range
assert self.range.source_buffer == other.range.source_buffer
return (self.range.begin_pos <= other.range.begin_pos <= self.range.end_pos and \ return (self.range.begin_pos <= other.range.begin_pos <= self.range.end_pos and \
other.range.end_pos > self.range.end_pos) or \ other.range.end_pos > self.range.end_pos) or \
@ -172,7 +172,7 @@ class AssignedNamesOf(algorithm.Visitor):
visit_SubscriptT = visit_accessor visit_SubscriptT = visit_accessor
def visit_sequence(self, node): def visit_sequence(self, node):
return reduce(list.__add__, map(self.visit, node.elts)) return functools.reduce(list.__add__, map(self.visit, node.elts))
visit_TupleT = visit_sequence visit_TupleT = visit_sequence
visit_ListT = visit_sequence visit_ListT = visit_sequence
@ -259,7 +259,6 @@ class EscapeValidator(algorithm.Visitor):
# this property. But we will need to, if string operations are ever added. # this property. But we will need to, if string operations are ever added.
def visit_assignment(self, target, value, is_aug_assign=False): def visit_assignment(self, target, value, is_aug_assign=False):
target_region = self._region_of(target)
value_region = self._region_of(value) if not is_aug_assign else self.youngest_region value_region = self._region_of(value) if not is_aug_assign else self.youngest_region
# If this is a variable, we might need to contract the live range. # If this is a variable, we might need to contract the live range.
@ -270,23 +269,25 @@ class EscapeValidator(algorithm.Visitor):
region.contract(value_region) region.contract(value_region)
# The assigned value should outlive the assignee # The assigned value should outlive the assignee
if not Region.outlives(value_region, target_region): target_regions = [self._region_of(name) for name in self._names_of(target)]
if is_aug_assign: for target_region in target_regions:
target_desc = "the assignment target, allocated here," if not Region.outlives(value_region, target_region):
else: if is_aug_assign:
target_desc = "the assignment target" target_desc = "the assignment target, allocated here,"
note = diagnostic.Diagnostic("note", else:
"this expression has type {type}", target_desc = "the assignment target"
{"type": types.TypePrinter().name(value.type)}, note = diagnostic.Diagnostic("note",
value.loc) "this expression has type {type}",
diag = diagnostic.Diagnostic("error", {"type": types.TypePrinter().name(value.type)},
"the assigned value does not outlive the assignment target", {}, value.loc)
value.loc, [target.loc], diag = diagnostic.Diagnostic("error",
notes=self._diagnostics_for(target_region, target.loc, "the assigned value does not outlive the assignment target", {},
target_desc) + value.loc, [target.loc],
self._diagnostics_for(value_region, value.loc, notes=self._diagnostics_for(target_region, target.loc,
"the assigned value")) target_desc) +
self.engine.process(diag) self._diagnostics_for(value_region, value.loc,
"the assigned value"))
self.engine.process(diag)
def visit_Assign(self, node): def visit_Assign(self, node):
for target in node.targets: for target in node.targets:

View File

@ -0,0 +1,5 @@
# RUN: %python -m artiq.compiler.testbench.signature %s
def f():
x, y = [0], [0]
x[0], y[0]