Commit 68dfde1d authored by Vitja Makarov's avatar Vitja Makarov

Remove old control flow stuff (analyse_control_flow is still there)

parent dd389de8
import bisect, sys
# This module keeps track of arbitrary "states" at any point of the code.
# A state is considered known if every path to the given point agrees on
# its state, otherwise it is None (i.e. unknown).
# It might be useful to be able to "freeze" the set of states by pushing
# all state changes to the tips of the trees for fast reading. Perhaps this
# could be done on get_state, clearing the cache on set_state (assuming
# incoming is immutable).
# This module still needs a lot of work, and probably should totally be
# redesigned. It doesn't take return, raise, continue, or break into
# account.
from Cython.Compiler.Scanning import StringSourceDescriptor
try:
_END_POS = (StringSourceDescriptor(unichr(sys.maxunicode)*10, ''),
sys.maxint, sys.maxint)
except AttributeError: # Py3
_END_POS = (StringSourceDescriptor(unichr(sys.maxunicode)*10, ''),
sys.maxsize, sys.maxsize)
class ControlFlow(object):
def __init__(self, start_pos, incoming, parent):
self.start_pos = start_pos
self.incoming = incoming
if parent is None and incoming is not None:
parent = incoming.parent
self.parent = parent
self.tip = {}
self.end_pos = _END_POS
def start_branch(self, pos):
self.end_pos = pos
branch_point = BranchingControlFlow(pos, self)
if self.parent is not None:
self.parent.branches[-1] = branch_point
return branch_point.branches[0]
def next_branch(self, pos):
self.end_pos = pos
return self.parent.new_branch(pos)
def finish_branch(self, pos):
self.end_pos = pos
self.parent.end_pos = pos
return LinearControlFlow(pos, self.parent)
def get_state(self, item, pos=_END_POS):
return self.get_pos_state(item, pos)[1]
def get_pos_state(self, item, pos=_END_POS):
# do some caching
if pos > self.end_pos:
try:
return self.tip[item]
except KeyError:
pass
pos_state = self._get_pos_state(item, pos)
if pos > self.end_pos:
self.tip[item] = pos_state
return pos_state
def _get_pos_state(self, item, pos):
current = self
while current is not None and pos <= current.start_pos:
current = current.incoming
if current is None:
return (None, None)
state = current._get_pos_state_local(item, pos)
while (state is None or state == (None, None)) and current.incoming is not None:
current = current.incoming
state = current._get_pos_state_local(item, pos)
if state is None:
return (None, None)
return state
def set_state(self, pos, item, state):
if item in self.tip:
del self.tip[item]
current = self
while pos < current.start_pos and current.incoming is not None:
current = current.incoming
if item in current.tip:
del current.tip[item]
current._set_state_local(pos, item, state)
class LinearControlFlow(ControlFlow):
def __init__(self, start_pos=(), incoming=None, parent=None):
ControlFlow.__init__(self, start_pos, incoming, parent)
self.events = {}
def _set_state_local(self, pos, item, state):
if item in self.events:
event_list = self.events[item]
else:
event_list = []
self.events[item] = event_list
bisect.insort(event_list, (pos, state))
def _get_pos_state_local(self, item, pos):
if item in self.events:
event_list = self.events[item]
for event in event_list[::-1]:
if event[0] < pos:
return event
return None
def to_string(self, indent='', limit=None):
if len(self.events) == 0:
s = indent + "[no state changes]"
else:
all = []
for item, event_list in self.events.items():
for pos, state in event_list:
all.append((indent, pos, item, state))
all.sort()
all = ["%s%s: %s <- %s" % data for data in all]
s = "\n".join(all)
if self.incoming is not limit and self.incoming is not None:
s = "%s\n%s" % (self.incoming.to_string(indent, limit=limit), s)
return s
class BranchingControlFlow(ControlFlow):
def __init__(self, start_pos, incoming, parent=None):
ControlFlow.__init__(self, start_pos, incoming, parent)
self.branches = [LinearControlFlow(start_pos, incoming, parent=self)]
self.branch_starts = [start_pos]
def _set_state_local(self, pos, item, state):
for branch_pos, branch in zip(self.branch_starts[::-1], self.branches[::-1]):
if pos >= branch_pos:
branch._set_state_local(pos, item, state)
return
def _get_pos_state_local(self, item, pos, stop_at=None):
if pos < self.end_pos:
for branch_pos, branch in zip(self.branch_starts[::-1], self.branches[::-1]):
if pos >= branch_pos:
return branch._get_pos_state_local(item, pos)
else:
state = self.branches[0]._get_pos_state_local(item, pos)
if state is None:
return None, None
last_pos, last_state = state
if last_state is None:
return None, None
for branch in self.branches[1:]:
state = branch._get_pos_state_local(item, pos)
if state is None:
return None, None
other_pos, other_state = state
if other_state != last_state:
return None, None
elif last_pos is not other_pos:
last_pos = max(last_pos, other_pos)
return last_pos, last_state
return None
def new_branch(self, pos):
self.branches.append(LinearControlFlow(pos, self.incoming, parent=self))
self.branch_starts.append(pos)
return self.branches[-1]
def to_string(self, indent='', limit=None):
join = "\n%sor\n" % indent
s = join.join([branch.to_string(indent+" ", limit=self.incoming) for branch in self.branches])
if self.incoming is not limit and self.incoming is not None:
s = "%s\n%s" % (self.incoming.to_string(indent, limit=limit), s)
return s
...@@ -1392,8 +1392,6 @@ class NameNode(AtomicExprNode): ...@@ -1392,8 +1392,6 @@ class NameNode(AtomicExprNode):
else: else:
type = py_object_type type = py_object_type
self.entry = env.declare_var(self.name, type, self.pos) self.entry = env.declare_var(self.name, type, self.pos)
env.control_flow.set_state(self.pos, (self.name, 'initialized'), True)
env.control_flow.set_state(self.pos, (self.name, 'source'), 'assignment')
if self.entry.is_declared_generic: if self.entry.is_declared_generic:
self.result_ctype = py_object_type self.result_ctype = py_object_type
......
...@@ -25,7 +25,6 @@ from Cython.Utils import open_new_file, replace_suffix ...@@ -25,7 +25,6 @@ from Cython.Utils import open_new_file, replace_suffix
from Code import UtilityCode, ClosureTempAllocator from Code import UtilityCode, ClosureTempAllocator
from StringEncoding import EncodedString, escape_byte_string, split_string_literal from StringEncoding import EncodedString, escape_byte_string, split_string_literal
import Options import Options
import ControlFlow
import DebugFlags import DebugFlags
absolute_path_length = 0 absolute_path_length = 0
...@@ -2249,9 +2248,6 @@ class DefNode(FuncDefNode): ...@@ -2249,9 +2248,6 @@ class DefNode(FuncDefNode):
for arg in self.args: for arg in self.args:
if not arg.name: if not arg.name:
error(arg.pos, "Missing argument name") error(arg.pos, "Missing argument name")
else:
env.control_flow.set_state((), (arg.name, 'source'), 'arg')
env.control_flow.set_state((), (arg.name, 'initialized'), True)
if arg.needs_conversion: if arg.needs_conversion:
arg.entry = env.declare_var(arg.name, arg.type, arg.pos) arg.entry = env.declare_var(arg.name, arg.type, arg.pos)
if arg.type.is_pyobject: if arg.type.is_pyobject:
...@@ -2278,7 +2274,6 @@ class DefNode(FuncDefNode): ...@@ -2278,7 +2274,6 @@ class DefNode(FuncDefNode):
entry.init = "0" entry.init = "0"
entry.xdecref_cleanup = 1 entry.xdecref_cleanup = 1
arg.entry = entry arg.entry = entry
env.control_flow.set_state((), (arg.name, 'initialized'), True)
def analyse_expressions(self, env): def analyse_expressions(self, env):
self.local_scope.directives = env.directives self.local_scope.directives = env.directives
...@@ -4347,13 +4342,10 @@ class IfStatNode(StatNode): ...@@ -4347,13 +4342,10 @@ class IfStatNode(StatNode):
child_attrs = ["if_clauses", "else_clause"] child_attrs = ["if_clauses", "else_clause"]
def analyse_control_flow(self, env): def analyse_control_flow(self, env):
env.start_branching(self.pos)
for if_clause in self.if_clauses: for if_clause in self.if_clauses:
if_clause.analyse_control_flow(env) if_clause.analyse_control_flow(env)
env.next_branch(if_clause.end_pos())
if self.else_clause: if self.else_clause:
self.else_clause.analyse_control_flow(env) self.else_clause.analyse_control_flow(env)
env.finish_branching(self.end_pos())
def analyse_declarations(self, env): def analyse_declarations(self, env):
for if_clause in self.if_clauses: for if_clause in self.if_clauses:
...@@ -4499,12 +4491,9 @@ class SwitchStatNode(StatNode): ...@@ -4499,12 +4491,9 @@ class SwitchStatNode(StatNode):
class LoopNode(object): class LoopNode(object):
def analyse_control_flow(self, env): def analyse_control_flow(self, env):
env.start_branching(self.pos)
self.body.analyse_control_flow(env) self.body.analyse_control_flow(env)
env.next_branch(self.body.end_pos())
if self.else_clause: if self.else_clause:
self.else_clause.analyse_control_flow(env) self.else_clause.analyse_control_flow(env)
env.finish_branching(self.end_pos())
class WhileStatNode(LoopNode, StatNode): class WhileStatNode(LoopNode, StatNode):
...@@ -5044,22 +5033,14 @@ class TryExceptStatNode(StatNode): ...@@ -5044,22 +5033,14 @@ class TryExceptStatNode(StatNode):
child_attrs = ["body", "except_clauses", "else_clause"] child_attrs = ["body", "except_clauses", "else_clause"]
def analyse_control_flow(self, env): def analyse_control_flow(self, env):
env.start_branching(self.pos)
self.body.analyse_control_flow(env) self.body.analyse_control_flow(env)
successful_try = env.control_flow # grab this for later
env.next_branch(self.body.end_pos())
env.finish_branching(self.body.end_pos())
env.start_branching(self.except_clauses[0].pos)
for except_clause in self.except_clauses: for except_clause in self.except_clauses:
except_clause.analyse_control_flow(env) except_clause.analyse_control_flow(env)
env.next_branch(except_clause.end_pos())
# the else cause it executed only when the try clause finishes # the else cause it executed only when the try clause finishes
env.control_flow.incoming = successful_try
if self.else_clause: if self.else_clause:
self.else_clause.analyse_control_flow(env) self.else_clause.analyse_control_flow(env)
env.finish_branching(self.end_pos())
def analyse_declarations(self, env): def analyse_declarations(self, env):
self.body.analyse_declarations(env) self.body.analyse_declarations(env)
...@@ -5382,10 +5363,7 @@ class TryFinallyStatNode(StatNode): ...@@ -5382,10 +5363,7 @@ class TryFinallyStatNode(StatNode):
create_analysed = staticmethod(create_analysed) create_analysed = staticmethod(create_analysed)
def analyse_control_flow(self, env): def analyse_control_flow(self, env):
env.start_branching(self.pos)
self.body.analyse_control_flow(env) self.body.analyse_control_flow(env)
env.next_branch(self.body.end_pos())
env.finish_branching(self.body.end_pos())
self.finally_clause.analyse_control_flow(env) self.finally_clause.analyse_control_flow(env)
def analyse_declarations(self, env): def analyse_declarations(self, env):
......
...@@ -13,7 +13,6 @@ import TypeSlots ...@@ -13,7 +13,6 @@ import TypeSlots
from TypeSlots import \ from TypeSlots import \
pyfunction_signature, pymethod_signature, \ pyfunction_signature, pymethod_signature, \
get_special_method_signature, get_property_accessor_signature get_special_method_signature, get_property_accessor_signature
import ControlFlow
import Code import Code
import __builtin__ as builtins import __builtin__ as builtins
try: try:
...@@ -224,7 +223,6 @@ class Scope(object): ...@@ -224,7 +223,6 @@ class Scope(object):
# qualified_name string "modname" or "modname.classname" # qualified_name string "modname" or "modname.classname"
# pystring_entries [Entry] String const entries newly used as # pystring_entries [Entry] String const entries newly used as
# Python strings in this scope # Python strings in this scope
# control_flow ControlFlow Used for keeping track of environment state
# nogil boolean In a nogil section # nogil boolean In a nogil section
# directives dict Helper variable for the recursive # directives dict Helper variable for the recursive
# analysis, contains directive values. # analysis, contains directive values.
...@@ -276,19 +274,9 @@ class Scope(object): ...@@ -276,19 +274,9 @@ class Scope(object):
self.pystring_entries = [] self.pystring_entries = []
self.buffer_entries = [] self.buffer_entries = []
self.lambda_defs = [] self.lambda_defs = []
self.control_flow = ControlFlow.LinearControlFlow()
self.return_type = None self.return_type = None
self.id_counters = {} self.id_counters = {}
def start_branching(self, pos):
self.control_flow = self.control_flow.start_branch(pos)
def next_branch(self, pos):
self.control_flow = self.control_flow.next_branch(pos)
def finish_branching(self, pos):
self.control_flow = self.control_flow.finish_branch(pos)
def __str__(self): def __str__(self):
return "<%s %s>" % (self.__class__.__name__, self.qualified_name) return "<%s %s>" % (self.__class__.__name__, self.qualified_name)
...@@ -528,7 +516,6 @@ class Scope(object): ...@@ -528,7 +516,6 @@ class Scope(object):
if api: if api:
entry.api = 1 entry.api = 1
entry.used = 1 entry.used = 1
self.control_flow.set_state((), (name, 'initialized'), False)
return entry return entry
def declare_builtin(self, name, pos): def declare_builtin(self, name, pos):
...@@ -1374,7 +1361,6 @@ class LocalScope(Scope): ...@@ -1374,7 +1361,6 @@ class LocalScope(Scope):
entry.is_arg = 1 entry.is_arg = 1
#entry.borrowed = 1 # Not using borrowed arg refs for now #entry.borrowed = 1 # Not using borrowed arg refs for now
self.arg_entries.append(entry) self.arg_entries.append(entry)
self.control_flow.set_state((), (name, 'source'), 'arg')
return entry return entry
def declare_var(self, name, type, pos, def declare_var(self, name, type, 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