Commit 5f96c010 authored by Vitja Makarov's avatar Vitja Makarov

NameNode: add control flow hint flags

parent 450e56ea
...@@ -1267,14 +1267,18 @@ class NameNode(AtomicExprNode): ...@@ -1267,14 +1267,18 @@ class NameNode(AtomicExprNode):
# name string Python name of the variable # name string Python name of the variable
# entry Entry Symbol table entry # entry Entry Symbol table entry
# type_entry Entry For extension type names, the original type entry # type_entry Entry For extension type names, the original type entry
# cf_is_null boolean Is uninitialized before this node
# cf_maybe_null boolean Maybe uninitialized before this node
is_name = True is_name = True
is_cython_module = False is_cython_module = False
cython_attribute = None cython_attribute = None
lhs_of_first_assignment = False lhs_of_first_assignment = False # TODO: remove me
is_used_as_rvalue = 0 is_used_as_rvalue = 0
entry = None entry = None
type_entry = None type_entry = None
cf_maybe_null = True
cf_is_null = False
def create_analysed_rvalue(pos, env, entry): def create_analysed_rvalue(pos, env, entry):
node = NameNode(pos) node = NameNode(pos)
...@@ -1550,15 +1554,11 @@ class NameNode(AtomicExprNode): ...@@ -1550,15 +1554,11 @@ class NameNode(AtomicExprNode):
code.error_goto_if_null(self.result(), self.pos))) code.error_goto_if_null(self.result(), self.pos)))
code.put_gotref(self.py_result()) code.put_gotref(self.py_result())
elif entry.is_local and False: elif entry.is_local:
# control flow not good enough yet if entry.type.is_pyobject:
assigned = entry.scope.control_flow.get_state((entry.name, 'initialized'), self.pos) if self.cf_maybe_null or self.cf_is_null:
if assigned is False: code.putln('if (%s == 0) { PyErr_SetString(PyExc_UnboundLocalError, "%s"); %s }' %
error(self.pos, "local variable '%s' referenced before assignment" % entry.name) (entry.cname, entry.name, code.error_goto(self.pos)))
elif not Options.init_local_none and assigned is None:
code.putln('if (%s == 0) { PyErr_SetString(PyExc_UnboundLocalError, "%s"); %s }' %
(entry.cname, entry.name, code.error_goto(self.pos)))
entry.scope.control_flow.set_state(self.pos, (entry.name, 'initialized'), True)
def generate_assignment_code(self, rhs, code): def generate_assignment_code(self, rhs, code):
#print "NameNode.generate_assignment_code:", self.name ### #print "NameNode.generate_assignment_code:", self.name ###
...@@ -1627,17 +1627,20 @@ class NameNode(AtomicExprNode): ...@@ -1627,17 +1627,20 @@ class NameNode(AtomicExprNode):
if self.use_managed_ref: if self.use_managed_ref:
rhs.make_owned_reference(code) rhs.make_owned_reference(code)
is_external_ref = entry.is_cglobal or self.entry.in_closure or self.entry.from_closure is_external_ref = entry.is_cglobal or self.entry.in_closure or self.entry.from_closure
if not self.lhs_of_first_assignment: if is_external_ref:
if is_external_ref: if not self.cf_is_null:
code.put_gotref(self.py_result()) if self.cf_maybe_null:
if entry.is_local and not Options.init_local_none: code.put_xgotref(self.py_result())
initialized = entry.scope.control_flow.get_state((entry.name, 'initialized'), self.pos) else:
if initialized is True: code.put_gotref(self.py_result())
code.put_decref(self.result(), self.ctype()) if entry.is_local:
elif initialized is None: if not self.cf_is_null:
if self.cf_maybe_null:
code.put_xdecref(self.result(), self.ctype()) code.put_xdecref(self.result(), self.ctype())
else: else:
code.put_decref(self.result(), self.ctype()) code.put_decref(self.result(), self.ctype())
else:
code.put_decref(self.result(), self.ctype())
if is_external_ref: if is_external_ref:
code.put_giveref(rhs.py_result()) code.put_giveref(rhs.py_result())
...@@ -1686,8 +1689,12 @@ class NameNode(AtomicExprNode): ...@@ -1686,8 +1689,12 @@ class NameNode(AtomicExprNode):
Naming.module_cname, Naming.module_cname,
self.entry.name)) self.entry.name))
elif self.entry.type.is_pyobject: elif self.entry.type.is_pyobject:
# Fake it until we can do it for real... if not self.cf_is_null:
self.generate_assignment_code(NoneNode(self.pos), code) if self.cf_maybe_null:
code.put_xdecref(self.result(), self.ctype())
else:
code.put_decref(self.result(), self.ctype())
code.putln('%s = NULL;' % self.result())
else: else:
error(self.pos, "Deletion of C names not supported") error(self.pos, "Deletion of C names not supported")
......
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