1.1 --- a/micropython/data.py Mon Jul 04 23:50:02 2011 +0200
1.2 +++ b/micropython/data.py Tue Jul 05 00:36:54 2011 +0200
1.3 @@ -236,6 +236,10 @@
1.4 assignments in the lifetime of a program).
1.5 """
1.6
1.7 + if value is None:
1.8 + print "Warning: name %r in namespace %r has an unknown value (evaluated to None)." % (name, self.full_name())
1.9 + value = Instance()
1.10 +
1.11 if name in self.globals:
1.12 self.module.set(name, value, 0)
1.13 else:
1.14 @@ -928,11 +932,15 @@
1.15 many assignments may be involved.
1.16 """
1.17
1.18 + if self.context_values.issuperset(context_values) and \
1.19 + not (Instance(), Instance()) in context_values:
1.20 + return
1.21 +
1.22 if self.assignments is None:
1.23 if single_assignment:
1.24 - self.assignments = 1
1.25 + self.assignments = len(set(context_values))
1.26 else:
1.27 - self.assignments = AtLeast(1)
1.28 + self.assignments = AtLeast(len(set(context_values)))
1.29 else:
1.30 if single_assignment:
1.31 self.assignments += 1
1.32 @@ -1079,6 +1087,15 @@
1.33 def __repr__(self):
1.34 return "Instance()"
1.35
1.36 + def __eq__(self, other):
1.37 + return other.__class__ is Instance
1.38 +
1.39 + def __ne__(self, other):
1.40 + return not self.__eq__(other)
1.41 +
1.42 + def __hash__(self):
1.43 + return 0
1.44 +
1.45 __shortrepr__ = __repr__
1.46
1.47 class Constant:
1.48 @@ -1111,7 +1128,11 @@
1.49 # Support constants as dictionary keys in order to build constant tables.
1.50
1.51 def __eq__(self, other):
1.52 - return other is not None and self.value == other.value and self.value.__class__ is other.value.__class__
1.53 + return other is not None and isinstance(other, Const) and \
1.54 + self.value == other.value and self.value.__class__ is other.value.__class__
1.55 +
1.56 + def __ne__(self, other):
1.57 + return not self.__eq__(other)
1.58
1.59 def __hash__(self):
1.60 return hash(self.value)
2.1 --- a/micropython/inspect.py Mon Jul 04 23:50:02 2011 +0200
2.2 +++ b/micropython/inspect.py Tue Jul 05 00:36:54 2011 +0200
2.3 @@ -171,7 +171,7 @@
2.4 if isinstance(n, compiler.ast.Global):
2.5 for name in n.names:
2.6 if not self.has_key(name):
2.7 - self[name] = None
2.8 + self[name] = Instance()
2.9 else:
2.10 self.process_globals(n)
2.11
2.12 @@ -419,7 +419,6 @@
2.13 def NOP(self, node):
2.14 for n in node.getChildNodes():
2.15 self.dispatch(n)
2.16 - return None
2.17
2.18 def NOP_ABANDON(self, node):
2.19 self.NOP(node)
2.20 @@ -469,21 +468,21 @@
2.21 if attrname == "__class__" and isinstance(value, Class):
2.22 attr = type_class
2.23 else:
2.24 - attr = value.get(attrname)
2.25 + attr = value.get(attrname) or Instance()
2.26 self.use_specific_attribute(value.full_name(), attrname)
2.27
2.28 elif isinstance(value, UnresolvedName):
2.29 attr = UnresolvedName(attrname, value.full_name(), self)
2.30
2.31 else:
2.32 - attr = None
2.33 + attr = Instance()
2.34
2.35 # Note usage of the attribute where a local is involved.
2.36
2.37 self._visitAttrUser(expr, attrname, node)
2.38
2.39 else:
2.40 - attr = None
2.41 + attr = Instance()
2.42 self.use_name(attrname, node)
2.43
2.44 return attr
2.45 @@ -613,7 +612,6 @@
2.46 for n in node.nodes:
2.47 self.dispatch(n)
2.48 self.in_assignment = 0
2.49 - return None
2.50
2.51 def visitAssAttr(self, node):
2.52 expr = self.dispatch(node.expr)
2.53 @@ -642,8 +640,6 @@
2.54 else:
2.55 self.use_name(attrname, node)
2.56
2.57 - return None
2.58 -
2.59 def visitAssList(self, node):
2.60
2.61 # Declare names which will be used by generated code.
2.62 @@ -655,7 +651,6 @@
2.63 for i, n in enumerate(node.nodes):
2.64 self.dispatch(n)
2.65 self._visitConst(i) # for __getitem__(i) at run-time
2.66 - return None
2.67
2.68 def visitAssName(self, node):
2.69 if hasattr(node, "flags") and node.flags == "OP_DELETE":
2.70 @@ -677,8 +672,6 @@
2.71 ns = self.get_namespace().full_name()
2.72 self.use_specific_attribute(fn.parent.full_name(), fn.name, "%s.%s" % (ns, node.name))
2.73
2.74 - return None
2.75 -
2.76 visitAssTuple = visitAssList
2.77
2.78 def visitAugAssign(self, node):
2.79 @@ -705,8 +698,6 @@
2.80 self.use_specific_attribute("__builtins__", "slice")
2.81 self.use_name("__setitem__", node)
2.82
2.83 - return None
2.84 -
2.85 visitBackquote = OP
2.86
2.87 visitBitand = _visitBinary
2.88 @@ -730,7 +721,7 @@
2.89
2.90 if self.namespaces:
2.91 print "Warning: class %r in %r is not global: ignored." % (node.name, self.namespaces[-1].full_name())
2.92 - return None
2.93 + return
2.94 else:
2.95 if self.in_loop:
2.96 print "Warning: class %r in %r defined in a loop." % (node.name, self.full_name())
2.97 @@ -757,7 +748,7 @@
2.98
2.99 if isinstance(expr, Attr):
2.100 if expr.assignments != 1:
2.101 - raise InspectError("Base class %r for %r is not constant." % (base, cls.full_name()))
2.102 + raise InspectError("Base class %r for %r is not constant: %r" % (base, cls.full_name(), expr))
2.103 else:
2.104 cls.add_base(expr.get_value())
2.105
2.106 @@ -856,6 +847,11 @@
2.107 in_loop = self.in_loop
2.108 self.in_loop = 1
2.109 self.dispatch(node.list)
2.110 +
2.111 + # NOTE: Could generate AST nodes for the actual operations instead of
2.112 + # NOTE: manually generating code in micropython.ast.
2.113 +
2.114 + self.expr = Instance() # each element is a result of a function call
2.115 self.dispatch(node.assign)
2.116
2.117 # Enter the loop.
2.118 @@ -886,8 +882,6 @@
2.119
2.120 self.resume_broken_branches()
2.121
2.122 - return None
2.123 -
2.124 def visitFrom(self, node):
2.125 module = self.importer.load(node.modname, 1)
2.126
2.127 @@ -916,8 +910,6 @@
2.128 if isinstance(attr.get_value(), Module) and not attr.get_value().loaded:
2.129 self.importer.load(attr.get_value().name)
2.130
2.131 - return None
2.132 -
2.133 def visitFunction(self, node):
2.134 return self._visitFunction(node, node.name)
2.135
2.136 @@ -963,9 +955,24 @@
2.137 self.shelve_branch()
2.138
2.139 self.merge_branches()
2.140 - return None
2.141 +
2.142 + def visitIfExp(self, node):
2.143 + self.new_branchpoint()
2.144 +
2.145 + # Propagate attribute usage to branches.
2.146 +
2.147 + self.dispatch(node.test)
2.148
2.149 - visitIfExp = NOP
2.150 + self.new_branch(node.then)
2.151 + self.dispatch(node.then)
2.152 + self.shelve_branch()
2.153 +
2.154 + self.new_branch(node.else_)
2.155 + self.dispatch(node.else_)
2.156 + self.shelve_branch()
2.157 +
2.158 + self.merge_branches()
2.159 + return Instance() # either outcome is possible
2.160
2.161 def visitImport(self, node):
2.162 for name, alias in node.names:
2.163 @@ -976,15 +983,12 @@
2.164 module = self.importer.load(name) or UnresolvedName(None, name.split(".")[0], self)
2.165 self.store(name.split(".")[0], module)
2.166
2.167 - return None
2.168 -
2.169 visitInvert = _visitUnary
2.170
2.171 def visitKeyword(self, node):
2.172 self.dispatch(node.expr)
2.173 self._visitConst(node.name)
2.174 self.keyword_names.add(node.name)
2.175 - return None
2.176
2.177 def visitLambda(self, node):
2.178 fn = self._visitFunction(node, None)
2.179 @@ -995,12 +999,13 @@
2.180
2.181 def visitList(self, node):
2.182 self.use_specific_attribute("__builtins__", "list")
2.183 - self.OP(node)
2.184 + return self.OP(node)
2.185
2.186 def visitListComp(self, node):
2.187 for qual in node.quals:
2.188 self.dispatch(qual)
2.189 self.dispatch(node.expr)
2.190 + return Instance()
2.191
2.192 def visitListCompFor(self, node):
2.193 self.new_branchpoint()
2.194 @@ -1013,6 +1018,11 @@
2.195 in_loop = self.in_loop
2.196 self.in_loop = 1
2.197 self.dispatch(node.list)
2.198 +
2.199 + # NOTE: Could generate AST nodes for the actual operations instead of
2.200 + # NOTE: manually generating code in micropython.ast.
2.201 +
2.202 + self.expr = Instance() # each element is a result of a function call
2.203 self.dispatch(node.assign)
2.204
2.205 # Enter the loop.
2.206 @@ -1027,7 +1037,6 @@
2.207 self.in_loop = in_loop
2.208
2.209 self.merge_branches()
2.210 - return None
2.211
2.212 visitListCompIf = NOP
2.213
2.214 @@ -1043,7 +1052,7 @@
2.215 visitMul = _visitBinary
2.216
2.217 def visitName(self, node):
2.218 - return self.get_namespace().get_using_node(node.name, node)
2.219 + return self.get_namespace().get_using_node(node.name, node) or Instance()
2.220
2.221 visitNot = OP
2.222
2.223 @@ -1070,19 +1079,18 @@
2.224 visitRightShift = _visitBinary
2.225
2.226 def visitSlice(self, node):
2.227 - self._visitOperator(node, self.in_assignment and "AssSlice" or "Slice")
2.228 + return self._visitOperator(node, self.in_assignment and "AssSlice" or "Slice")
2.229
2.230 visitSliceobj = OP
2.231
2.232 def visitStmt(self, node):
2.233 for n in node.nodes:
2.234 self.dispatch(n)
2.235 - return None
2.236
2.237 visitSub = _visitBinary
2.238
2.239 def visitSubscript(self, node):
2.240 - self._visitOperator(node, self.in_assignment and "AssSubscript" or "Subscript")
2.241 + return self._visitOperator(node, self.in_assignment and "AssSubscript" or "Subscript")
2.242
2.243 def visitTryExcept(self, node):
2.244 self.dispatch(node.body)
2.245 @@ -1107,7 +1115,6 @@
2.246 self.shelve_branch()
2.247
2.248 self.merge_branches()
2.249 - return None
2.250
2.251 visitTryFinally = NOP
2.252
2.253 @@ -1155,8 +1162,6 @@
2.254
2.255 self.resume_broken_branches()
2.256
2.257 - return None
2.258 -
2.259 visitWith = NOP
2.260
2.261 visitYield = NOP