1.1 --- a/micropython/branch.py Mon Jan 13 23:58:23 2014 +0100
1.2 +++ b/micropython/branch.py Mon Jan 13 23:58:56 2014 +0100
1.3 @@ -1,7 +1,7 @@
1.4 #!/usr/bin/env python
1.5
1.6 """
1.7 -Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013 Paul Boddie <paul@boddie.org.uk>
1.8 +Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Paul Boddie <paul@boddie.org.uk>
1.9
1.10 This program is free software; you can redistribute it and/or modify it under
1.11 the terms of the GNU General Public License as published by the Free Software
1.12 @@ -414,6 +414,13 @@
1.13
1.14 self.scope_usage[-1][name] = scope
1.15
1.16 + def defined_as_local(self, name):
1.17 +
1.18 + "Return the scope defined for 'name' or None if it is not yet defined."
1.19 +
1.20 + scope = self.scope_usage[-1].get(name)
1.21 + return scope and (scope == "local" or isinstance(scope, ScopeConflict) and scope.is_benign())
1.22 +
1.23 def note_scope(self, name, scope):
1.24
1.25 """
1.26 @@ -426,8 +433,11 @@
1.27 if scope_usage.has_key(name):
1.28 found_scope = scope_usage[name]
1.29 if isinstance(found_scope, ScopeConflict):
1.30 - raise InspectError("Scope conflict for %r: defined as %s." % (
1.31 - name, ", ".join(found_scope.scopes)))
1.32 + if not found_scope.is_benign():
1.33 + raise InspectError("Scope conflict for %r: defined as %s." % (
1.34 + name, ", ".join(found_scope.scopes)))
1.35 + else:
1.36 + print >>sys.stderr, "Warning: name %r in %s may not be defined in all cases." % (name, self.full_name())
1.37
1.38 scope_usage[name] = scope
1.39
1.40 @@ -645,6 +655,8 @@
1.41
1.42 else:
1.43 attr, scope, full_name = self._get_with_scope(name, external=1)
1.44 + if not attr:
1.45 + scope = "unset"
1.46
1.47 # Attempt to record the scope, testing for conflicts.
1.48
1.49 @@ -748,13 +760,21 @@
1.50 class ScopeConflict:
1.51
1.52 """
1.53 - A scope conflict caused when different code branches contribute different
1.54 - sources of names.
1.55 + A class whose instances provide a collection of scope alternatives, either
1.56 + potentially benign or indicating a serious problem.
1.57 +
1.58 + A scope conflict is caused when different code branches contribute different
1.59 + sources of names or where branches neglect to contribute names at all. Where
1.60 + the sources (scopes) indicated are different, a serious problem exists
1.61 + because the name has no single way of being accessed.
1.62 """
1.63
1.64 def __init__(self, scopes):
1.65 self.scopes = scopes
1.66
1.67 + def is_benign(self):
1.68 + return len(self.scopes) == 2 and "unset" in self.scopes
1.69 +
1.70 class UnsetType:
1.71
1.72 "A None-like value."
2.1 --- a/micropython/data.py Mon Jan 13 23:58:23 2014 +0100
2.2 +++ b/micropython/data.py Mon Jan 13 23:58:56 2014 +0100
2.3 @@ -221,7 +221,7 @@
2.4
2.5 # Locals.
2.6
2.7 - if not external and self.has_key(name):
2.8 + if not external and self.defined_as_local(name) and self.has_key(name):
2.9 return self[name], "local", self.full_name()
2.10
2.11 # Outer scopes.
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/tests/local_potentially_unassigned.py Mon Jan 13 23:58:56 2014 +0100
3.3 @@ -0,0 +1,10 @@
3.4 +#!/usr/bin/env python
3.5 +
3.6 +def f(a):
3.7 + if a:
3.8 + x = 1
3.9 + return x
3.10 +
3.11 +result_1 = f(1)
3.12 +
3.13 +# vim: tabstop=4 expandtab shiftwidth=4