Commit 61e4baf6 authored by Stefan Behnel's avatar Stefan Behnel

reimplement cross-closure type inference using a dedicated LocalEntry class...

reimplement cross-closure type inference using a dedicated LocalEntry class for entry copies in closures to keep closure knowledge in one place
parent 5fdb48d4
......@@ -161,15 +161,15 @@ class ControlFlow(object):
self.block.positions.add(node.pos[:2])
def mark_assignment(self, lhs, rhs, entry):
if self.block:
if not self.is_tracked(entry):
return
entry = entry.defining_entry
if self.block and self.is_tracked(entry):
assignment = NameAssignment(lhs, rhs, entry)
self.block.stats.append(assignment)
self.block.gen[entry] = assignment
self.entries.add(entry)
def mark_argument(self, lhs, rhs, entry):
entry = entry.defining_entry
if self.block and self.is_tracked(entry):
assignment = Argument(lhs, rhs, entry)
self.block.stats.append(assignment)
......@@ -177,6 +177,7 @@ class ControlFlow(object):
self.entries.add(entry)
def mark_deletion(self, node, entry):
entry = entry.defining_entry
if self.block and self.is_tracked(entry):
assignment = NameDeletion(node, entry)
self.block.stats.append(assignment)
......@@ -184,6 +185,7 @@ class ControlFlow(object):
self.entries.add(entry)
def mark_reference(self, node, entry):
entry = entry.defining_entry
if self.block and self.is_tracked(entry):
self.block.stats.append(NameReference(node, entry))
# Local variable is definitely bound after this reference
......
......@@ -198,9 +198,10 @@ class Entry(object):
self.cf_assignments = []
self.cf_references = []
self.inner_entries = []
self.defining_entry = self
def __repr__(self):
return "Entry(name=%s, type=%s)" % (self.name, self.type)
return "%s(name=%s, type=%s)" % (type(self).__name__, self.name, self.type)
def redeclared(self, pos):
error(pos, "'%s' does not match previous declaration" % self.name)
......@@ -210,20 +211,36 @@ class Entry(object):
return [self] + self.overloaded_alternatives
def all_entries(self):
"""
Returns all entries for this entry, including the equivalent ones
in other closures.
"""
if self.from_closure:
return self.outer_entry.all_entries()
return [self] + self.inner_entries
entries = []
def collect_inner_entries(entry):
entries.append(entry)
for e in entry.inner_entries:
collect_inner_entries(e)
collect_inner_entries(self)
return entries
class InnerEntry(Entry):
"""
An entry in a closure scope that represents the real outer Entry.
"""
from_closure = True
def __init__(self, outer_entry, scope):
Entry.__init__(self, outer_entry.name,
outer_entry.cname,
outer_entry.type,
outer_entry.pos)
self.outer_entry = outer_entry
self.scope = scope
# share state with (outermost) defining entry
outermost_entry = outer_entry
while outermost_entry.outer_entry:
outermost_entry = outermost_entry.outer_entry
self.defining_entry = outermost_entry
self.inner_entries = outermost_entry.inner_entries
self.cf_assignments = outermost_entry.cf_assignments
self.cf_references = outermost_entry.cf_references
self.overloaded_alternatives = outermost_entry.overloaded_alternatives
self.inner_entries.append(self)
def __getattr__(self, name):
return getattr(self.defining_entry, name)
class Scope(object):
......@@ -1534,15 +1551,9 @@ class LocalScope(Scope):
# The actual c fragment for the different scopes differs
# on the outside and inside, so we make a new entry
entry.in_closure = True
# Would it be better to declare_var here?
inner_entry = Entry(entry.name, entry.cname, entry.type, entry.pos)
inner_entry.scope = self
inner_entry = InnerEntry(entry, self)
inner_entry.is_variable = True
inner_entry.outer_entry = entry
inner_entry.from_closure = True
inner_entry.is_declared_generic = entry.is_declared_generic
self.entries[name] = inner_entry
entry.inner_entries.append(inner_entry)
return inner_entry
return entry
......
......@@ -360,11 +360,9 @@ class SimpleAssignmentTypeInferer(object):
ready_to_infer = []
for name, entry in scope.entries.items():
if entry.type is unspecified_type:
entries = entry.all_entries()
all = set()
for e in entries:
for assmt in e.cf_assignments:
all.update(assmt.type_dependencies(e.scope))
for assmt in entry.cf_assignments:
all.update(assmt.type_dependencies(entry.scope))
if all:
dependancies_by_entry[entry] = all
for dep in all:
......@@ -390,8 +388,7 @@ class SimpleAssignmentTypeInferer(object):
entry = ready_to_infer.pop()
types = [
assmt.rhs.infer_type(scope)
for e in entry.all_entries()
for assmt in e.cf_assignments
for assmt in entry.cf_assignments
]
if types and Utils.all(types):
entry_type = spanning_type(types, entry.might_overflow, entry.pos)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment