Commit daf7dcec authored by Stefan Behnel's avatar Stefan Behnel

clean up and improve static type declarations in FlowControl.py a bit

parent cb2b3432
cimport cython cimport cython
from Cython.Compiler.Visitor cimport CythonTransform, TreeVisitor
cdef class ControlBlock: cdef class ControlBlock:
cdef public set children cdef public set children
cdef public set parents cdef public set parents
...@@ -39,6 +41,9 @@ cdef class AssignmentList: ...@@ -39,6 +41,9 @@ cdef class AssignmentList:
cdef public object mask cdef public object mask
cdef public list stats cdef public list stats
cdef class AssignmentCollector(TreeVisitor):
cdef list assignments
cdef class ControlFlow: cdef class ControlFlow:
cdef public set blocks cdef public set blocks
cdef public set entries cdef public set entries
...@@ -51,9 +56,10 @@ cdef class ControlFlow: ...@@ -51,9 +56,10 @@ cdef class ControlFlow:
cdef public dict assmts cdef public dict assmts
cpdef newblock(self, parent=*) cpdef newblock(self, ControlBlock parent=*)
cpdef nextblock(self, parent=*) cpdef nextblock(self, ControlBlock parent=*)
cpdef bint is_tracked(self, entry) cpdef bint is_tracked(self, entry)
cpdef bint is_statically_assigned(self, entry)
cpdef mark_position(self, node) cpdef mark_position(self, node)
cpdef mark_assignment(self, lhs, rhs, entry) cpdef mark_assignment(self, lhs, rhs, entry)
cpdef mark_argument(self, lhs, rhs, entry) cpdef mark_argument(self, lhs, rhs, entry)
...@@ -74,5 +80,20 @@ cdef class ControlFlow: ...@@ -74,5 +80,20 @@ cdef class ControlFlow:
cdef class Uninitialized: cdef class Uninitialized:
pass pass
cdef class Unknown:
pass
@cython.locals(dirty=bint, block=ControlBlock, parent=ControlBlock) @cython.locals(dirty=bint, block=ControlBlock, parent=ControlBlock)
cdef check_definitions(ControlFlow flow, dict compiler_directives) cdef check_definitions(ControlFlow flow, dict compiler_directives)
cdef class ControlFlowAnalysis(CythonTransform):
cdef object gv_ctx
cdef set reductions
cdef list env_stack
cdef list stack
cdef object env
cdef ControlFlow flow
cdef bint in_inplace_assignment
cpdef mark_assignment(self, lhs, rhs=*)
cpdef mark_position(self, node)
import cython import cython
cython.declare(PyrexTypes=object, Naming=object, ExprNodes=object, Nodes=object, cython.declare(PyrexTypes=object, ExprNodes=object, Nodes=object,
Options=object, UtilNodes=object, ModuleNode=object, Builtin=object, InternalError=object,
LetNode=object, LetRefNode=object, TreeFragment=object, error=object, warning=object,
TemplateTransform=object, EncodedString=object, py_object_type=object, unspecified_type=object,
error=object, warning=object, copy=object) object_expr=object, object_expr_not_none=object,
fake_rhs_expr=object, TypedExprNode=object)
import Builtin import Builtin
import ExprNodes import ExprNodes
...@@ -17,7 +18,7 @@ from Errors import error, warning, InternalError ...@@ -17,7 +18,7 @@ from Errors import error, warning, InternalError
class TypedExprNode(ExprNodes.ExprNode): class TypedExprNode(ExprNodes.ExprNode):
# Used for declaring assignments of a specified type without a known entry. # Used for declaring assignments of a specified type without a known entry.
def __init__(self, type, may_be_none=None, pos=None): def __init__(self, type, may_be_none=None, pos=None):
self.pos = pos super(TypedExprNode, self).__init__(pos)
self.type = type self.type = type
self._may_be_none = may_be_none self._may_be_none = may_be_none
...@@ -640,7 +641,7 @@ class AssignmentCollector(TreeVisitor): ...@@ -640,7 +641,7 @@ class AssignmentCollector(TreeVisitor):
self.assignments = [] self.assignments = []
def visit_Node(self): def visit_Node(self):
self.visitchildren(self) self._visitchildren(self, None)
def visit_SingleAssignmentNode(self, node): def visit_SingleAssignmentNode(self, node):
self.assignments.append((node.lhs, node.rhs)) self.assignments.append((node.lhs, node.rhs))
...@@ -651,7 +652,6 @@ class AssignmentCollector(TreeVisitor): ...@@ -651,7 +652,6 @@ class AssignmentCollector(TreeVisitor):
class ControlFlowAnalysis(CythonTransform): class ControlFlowAnalysis(CythonTransform):
in_inplace_assignment = False
def visit_ModuleNode(self, node): def visit_ModuleNode(self, node):
self.gv_ctx = GVContext() self.gv_ctx = GVContext()
...@@ -659,6 +659,7 @@ class ControlFlowAnalysis(CythonTransform): ...@@ -659,6 +659,7 @@ class ControlFlowAnalysis(CythonTransform):
# Set of NameNode reductions # Set of NameNode reductions
self.reductions = set() self.reductions = set()
self.in_inplace_assignment = False
self.env_stack = [] self.env_stack = []
self.env = node.scope self.env = node.scope
self.stack = [] self.stack = []
...@@ -681,7 +682,7 @@ class ControlFlowAnalysis(CythonTransform): ...@@ -681,7 +682,7 @@ class ControlFlowAnalysis(CythonTransform):
for arg in node.args: for arg in node.args:
if arg.default: if arg.default:
self.visitchildren(arg) self.visitchildren(arg)
self.visitchildren(node, attrs=('decorators',)) self.visitchildren(node, ('decorators',))
self.env_stack.append(self.env) self.env_stack.append(self.env)
self.env = node.local_scope self.env = node.local_scope
self.stack.append(self.flow) self.stack.append(self.flow)
...@@ -697,7 +698,7 @@ class ControlFlowAnalysis(CythonTransform): ...@@ -697,7 +698,7 @@ class ControlFlowAnalysis(CythonTransform):
self.flow.nextblock() self.flow.nextblock()
for arg in node.args: for arg in node.args:
self.visit(arg) self._visit(arg)
if node.star_arg: if node.star_arg:
self.flow.mark_argument(node.star_arg, self.flow.mark_argument(node.star_arg,
TypedExprNode(Builtin.tuple_type, TypedExprNode(Builtin.tuple_type,
...@@ -708,10 +709,10 @@ class ControlFlowAnalysis(CythonTransform): ...@@ -708,10 +709,10 @@ class ControlFlowAnalysis(CythonTransform):
TypedExprNode(Builtin.dict_type, TypedExprNode(Builtin.dict_type,
may_be_none=False), may_be_none=False),
node.starstar_arg.entry) node.starstar_arg.entry)
self.visit(node.body) self._visit(node.body)
# Workaround for generators # Workaround for generators
if node.is_generator: if node.is_generator:
self.visit(node.gbody.body) self._visit(node.gbody.body)
# Exit point # Exit point
if self.flow.block: if self.flow.block:
...@@ -760,7 +761,7 @@ class ControlFlowAnalysis(CythonTransform): ...@@ -760,7 +761,7 @@ class ControlFlowAnalysis(CythonTransform):
for arg in lhs.args: for arg in lhs.args:
self.mark_assignment(arg) self.mark_assignment(arg)
else: else:
self.visit(lhs) self._visit(lhs)
if self.flow.exceptions: if self.flow.exceptions:
exc_descr = self.flow.exceptions[-1] exc_descr = self.flow.exceptions[-1]
...@@ -783,12 +784,12 @@ class ControlFlowAnalysis(CythonTransform): ...@@ -783,12 +784,12 @@ class ControlFlowAnalysis(CythonTransform):
raise InternalError, "Unhandled assignment node" raise InternalError, "Unhandled assignment node"
def visit_SingleAssignmentNode(self, node): def visit_SingleAssignmentNode(self, node):
self.visit(node.rhs) self._visit(node.rhs)
self.mark_assignment(node.lhs, node.rhs) self.mark_assignment(node.lhs, node.rhs)
return node return node
def visit_CascadedAssignmentNode(self, node): def visit_CascadedAssignmentNode(self, node):
self.visit(node.rhs) self._visit(node.rhs)
for lhs in node.lhs_list: for lhs in node.lhs_list:
self.mark_assignment(lhs, node.rhs) self.mark_assignment(lhs, node.rhs)
return node return node
...@@ -797,7 +798,7 @@ class ControlFlowAnalysis(CythonTransform): ...@@ -797,7 +798,7 @@ class ControlFlowAnalysis(CythonTransform):
collector = AssignmentCollector() collector = AssignmentCollector()
collector.visitchildren(node) collector.visitchildren(node)
for lhs, rhs in collector.assignments: for lhs, rhs in collector.assignments:
self.visit(rhs) self._visit(rhs)
for lhs, rhs in collector.assignments: for lhs, rhs in collector.assignments:
self.mark_assignment(lhs, rhs) self.mark_assignment(lhs, rhs)
return node return node
...@@ -818,7 +819,7 @@ class ControlFlowAnalysis(CythonTransform): ...@@ -818,7 +819,7 @@ class ControlFlowAnalysis(CythonTransform):
"can not delete variable '%s' " "can not delete variable '%s' "
"referenced in nested scope" % entry.name) "referenced in nested scope" % entry.name)
# Mark reference # Mark reference
self.visit(arg) self._visit(arg)
self.flow.mark_deletion(arg, entry) self.flow.mark_deletion(arg, entry)
return node return node
...@@ -845,7 +846,7 @@ class ControlFlowAnalysis(CythonTransform): ...@@ -845,7 +846,7 @@ class ControlFlowAnalysis(CythonTransform):
def visit_StatListNode(self, node): def visit_StatListNode(self, node):
if self.flow.block: if self.flow.block:
for stat in node.stats: for stat in node.stats:
self.visit(stat) self._visit(stat)
if not self.flow.block: if not self.flow.block:
stat.is_terminator = True stat.is_terminator = True
break break
...@@ -862,15 +863,15 @@ class ControlFlowAnalysis(CythonTransform): ...@@ -862,15 +863,15 @@ class ControlFlowAnalysis(CythonTransform):
# If clauses # If clauses
for clause in node.if_clauses: for clause in node.if_clauses:
parent = self.flow.nextblock(parent) parent = self.flow.nextblock(parent)
self.visit(clause.condition) self._visit(clause.condition)
self.flow.nextblock() self.flow.nextblock()
self.visit(clause.body) self._visit(clause.body)
if self.flow.block: if self.flow.block:
self.flow.block.add_child(next_block) self.flow.block.add_child(next_block)
# Else clause # Else clause
if node.else_clause: if node.else_clause:
self.flow.nextblock(parent=parent) self.flow.nextblock(parent=parent)
self.visit(node.else_clause) self._visit(node.else_clause)
if self.flow.block: if self.flow.block:
self.flow.block.add_child(next_block) self.flow.block.add_child(next_block)
else: else:
...@@ -887,10 +888,10 @@ class ControlFlowAnalysis(CythonTransform): ...@@ -887,10 +888,10 @@ class ControlFlowAnalysis(CythonTransform):
next_block = self.flow.newblock() next_block = self.flow.newblock()
# Condition block # Condition block
self.flow.loops.append(LoopDescr(next_block, condition_block)) self.flow.loops.append(LoopDescr(next_block, condition_block))
self.visit(node.condition) self._visit(node.condition)
# Body block # Body block
self.flow.nextblock() self.flow.nextblock()
self.visit(node.body) self._visit(node.body)
self.flow.loops.pop() self.flow.loops.pop()
# Loop it # Loop it
if self.flow.block: if self.flow.block:
...@@ -899,7 +900,7 @@ class ControlFlowAnalysis(CythonTransform): ...@@ -899,7 +900,7 @@ class ControlFlowAnalysis(CythonTransform):
# Else clause # Else clause
if node.else_clause: if node.else_clause:
self.flow.nextblock(parent=condition_block) self.flow.nextblock(parent=condition_block)
self.visit(node.else_clause) self._visit(node.else_clause)
if self.flow.block: if self.flow.block:
self.flow.block.add_child(next_block) self.flow.block.add_child(next_block)
else: else:
...@@ -967,7 +968,7 @@ class ControlFlowAnalysis(CythonTransform): ...@@ -967,7 +968,7 @@ class ControlFlowAnalysis(CythonTransform):
next_block = self.flow.newblock() next_block = self.flow.newblock()
# Condition with iterator # Condition with iterator
self.flow.loops.append(LoopDescr(next_block, condition_block)) self.flow.loops.append(LoopDescr(next_block, condition_block))
self.visit(node.iterator) self._visit(node.iterator)
# Target assignment # Target assignment
self.flow.nextblock() self.flow.nextblock()
...@@ -982,7 +983,7 @@ class ControlFlowAnalysis(CythonTransform): ...@@ -982,7 +983,7 @@ class ControlFlowAnalysis(CythonTransform):
self._delete_privates(node, exclude=node.target.entry) self._delete_privates(node, exclude=node.target.entry)
self.flow.nextblock() self.flow.nextblock()
self.visit(node.body) self._visit(node.body)
self.flow.loops.pop() self.flow.loops.pop()
# Loop it # Loop it
...@@ -991,7 +992,7 @@ class ControlFlowAnalysis(CythonTransform): ...@@ -991,7 +992,7 @@ class ControlFlowAnalysis(CythonTransform):
# Else clause # Else clause
if node.else_clause: if node.else_clause:
self.flow.nextblock(parent=condition_block) self.flow.nextblock(parent=condition_block)
self.visit(node.else_clause) self._visit(node.else_clause)
if self.flow.block: if self.flow.block:
self.flow.block.add_child(next_block) self.flow.block.add_child(next_block)
else: else:
...@@ -1042,10 +1043,10 @@ class ControlFlowAnalysis(CythonTransform): ...@@ -1042,10 +1043,10 @@ class ControlFlowAnalysis(CythonTransform):
next_block = self.flow.newblock() next_block = self.flow.newblock()
# Condition with iterator # Condition with iterator
self.flow.loops.append(LoopDescr(next_block, condition_block)) self.flow.loops.append(LoopDescr(next_block, condition_block))
self.visit(node.bound1) self._visit(node.bound1)
self.visit(node.bound2) self._visit(node.bound2)
if node.step is not None: if node.step is not None:
self.visit(node.step) self._visit(node.step)
# Target assignment # Target assignment
self.flow.nextblock() self.flow.nextblock()
self.mark_assignment(node.target, node.bound1) self.mark_assignment(node.target, node.bound1)
...@@ -1055,7 +1056,7 @@ class ControlFlowAnalysis(CythonTransform): ...@@ -1055,7 +1056,7 @@ class ControlFlowAnalysis(CythonTransform):
node.bound1, node.step)) node.bound1, node.step))
# Body block # Body block
self.flow.nextblock() self.flow.nextblock()
self.visit(node.body) self._visit(node.body)
self.flow.loops.pop() self.flow.loops.pop()
# Loop it # Loop it
if self.flow.block: if self.flow.block:
...@@ -1063,7 +1064,7 @@ class ControlFlowAnalysis(CythonTransform): ...@@ -1063,7 +1064,7 @@ class ControlFlowAnalysis(CythonTransform):
# Else clause # Else clause
if node.else_clause: if node.else_clause:
self.flow.nextblock(parent=condition_block) self.flow.nextblock(parent=condition_block)
self.visit(node.else_clause) self._visit(node.else_clause)
if self.flow.block: if self.flow.block:
self.flow.block.add_child(next_block) self.flow.block.add_child(next_block)
else: else:
...@@ -1083,9 +1084,9 @@ class ControlFlowAnalysis(CythonTransform): ...@@ -1083,9 +1084,9 @@ class ControlFlowAnalysis(CythonTransform):
return node return node
def visit_WithStatNode(self, node): def visit_WithStatNode(self, node):
self.visit(node.manager) self._visit(node.manager)
self.visit(node.enter_call) self._visit(node.enter_call)
self.visit(node.body) self._visit(node.body)
return node return node
def visit_TryExceptStatNode(self, node): def visit_TryExceptStatNode(self, node):
...@@ -1100,14 +1101,14 @@ class ControlFlowAnalysis(CythonTransform): ...@@ -1100,14 +1101,14 @@ class ControlFlowAnalysis(CythonTransform):
## XXX: links to exception handling point should be added by ## XXX: links to exception handling point should be added by
## XXX: children nodes ## XXX: children nodes
self.flow.block.add_child(entry_point) self.flow.block.add_child(entry_point)
self.visit(node.body) self._visit(node.body)
self.flow.exceptions.pop() self.flow.exceptions.pop()
# After exception # After exception
if self.flow.block: if self.flow.block:
if node.else_clause: if node.else_clause:
self.flow.nextblock() self.flow.nextblock()
self.visit(node.else_clause) self._visit(node.else_clause)
if self.flow.block: if self.flow.block:
self.flow.block.add_child(next_block) self.flow.block.add_child(next_block)
...@@ -1115,7 +1116,7 @@ class ControlFlowAnalysis(CythonTransform): ...@@ -1115,7 +1116,7 @@ class ControlFlowAnalysis(CythonTransform):
self.flow.block = entry_point self.flow.block = entry_point
if clause.pattern: if clause.pattern:
for pattern in clause.pattern: for pattern in clause.pattern:
self.visit(pattern) self._visit(pattern)
else: else:
# TODO: handle * pattern # TODO: handle * pattern
pass pass
...@@ -1123,7 +1124,7 @@ class ControlFlowAnalysis(CythonTransform): ...@@ -1123,7 +1124,7 @@ class ControlFlowAnalysis(CythonTransform):
self.flow.nextblock() self.flow.nextblock()
if clause.target: if clause.target:
self.mark_assignment(clause.target) self.mark_assignment(clause.target)
self.visit(clause.body) self._visit(clause.body)
if self.flow.block: if self.flow.block:
self.flow.block.add_child(next_block) self.flow.block.add_child(next_block)
...@@ -1142,7 +1143,7 @@ class ControlFlowAnalysis(CythonTransform): ...@@ -1142,7 +1143,7 @@ class ControlFlowAnalysis(CythonTransform):
# Exception entry point # Exception entry point
entry_point = self.flow.newblock() entry_point = self.flow.newblock()
self.flow.block = entry_point self.flow.block = entry_point
self.visit(node.finally_clause) self._visit(node.finally_clause)
if self.flow.block and self.flow.exceptions: if self.flow.block and self.flow.exceptions:
self.flow.block.add_child(self.flow.exceptions[-1].entry_point) self.flow.block.add_child(self.flow.exceptions[-1].entry_point)
...@@ -1150,7 +1151,7 @@ class ControlFlowAnalysis(CythonTransform): ...@@ -1150,7 +1151,7 @@ class ControlFlowAnalysis(CythonTransform):
# Normal execution # Normal execution
finally_enter = self.flow.newblock() finally_enter = self.flow.newblock()
self.flow.block = finally_enter self.flow.block = finally_enter
self.visit(node.finally_clause) self._visit(node.finally_clause)
finally_exit = self.flow.block finally_exit = self.flow.block
descr = ExceptionDescr(entry_point, finally_enter, finally_exit) descr = ExceptionDescr(entry_point, finally_enter, finally_exit)
...@@ -1160,7 +1161,7 @@ class ControlFlowAnalysis(CythonTransform): ...@@ -1160,7 +1161,7 @@ class ControlFlowAnalysis(CythonTransform):
self.flow.block = body_block self.flow.block = body_block
## XXX: Is it still required ## XXX: Is it still required
body_block.add_child(entry_point) body_block.add_child(entry_point)
self.visit(node.body) self._visit(node.body)
self.flow.exceptions.pop() self.flow.exceptions.pop()
if self.flow.loops: if self.flow.loops:
self.flow.loops[-1].exceptions.pop() self.flow.loops[-1].exceptions.pop()
...@@ -1243,8 +1244,8 @@ class ControlFlowAnalysis(CythonTransform): ...@@ -1243,8 +1244,8 @@ class ControlFlowAnalysis(CythonTransform):
self.env_stack.append(self.env) self.env_stack.append(self.env)
self.env = node.expr_scope self.env = node.expr_scope
# Skip append node here # Skip append node here
self.visit(node.target) self._visit(node.target)
self.visit(node.loop) self._visit(node.loop)
if node.expr_scope: if node.expr_scope:
self.env = self.env_stack.pop() self.env = self.env_stack.pop()
return node return node
...@@ -1259,14 +1260,14 @@ class ControlFlowAnalysis(CythonTransform): ...@@ -1259,14 +1260,14 @@ class ControlFlowAnalysis(CythonTransform):
return node return node
def visit_PyClassDefNode(self, node): def visit_PyClassDefNode(self, node):
self.visitchildren(node, attrs=('dict', 'metaclass', self.visitchildren(node, ('dict', 'metaclass',
'mkw', 'bases', 'class_result')) 'mkw', 'bases', 'class_result'))
self.flow.mark_assignment(node.target, object_expr_not_none, self.flow.mark_assignment(node.target, object_expr_not_none,
self.env.lookup(node.name)) self.env.lookup(node.name))
self.env_stack.append(self.env) self.env_stack.append(self.env)
self.env = node.scope self.env = node.scope
self.flow.nextblock() self.flow.nextblock()
self.visitchildren(node, attrs=('body',)) self.visitchildren(node, ('body',))
self.flow.nextblock() self.flow.nextblock()
self.env = self.env_stack.pop() self.env = self.env_stack.pop()
return node return node
......
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