1.1 --- a/micropython/ast.py Mon Mar 10 00:37:37 2008 +0100
1.2 +++ b/micropython/ast.py Wed Mar 19 20:57:38 2008 +0100
1.3 @@ -67,6 +67,7 @@
1.4 self.labels = {}
1.5 self.label_number = 0
1.6 self.loop_labels = []
1.7 + self.exception_labels = []
1.8
1.9 # The code itself.
1.10
1.11 @@ -124,6 +125,24 @@
1.12
1.13 label.location = len(self.code) + self.unit.code_location
1.14
1.15 + def get_loop_labels(self):
1.16 + return self.loop_labels[-1]
1.17 +
1.18 + def add_loop_labels(self, next_label, exit_label):
1.19 + self.loop_labels.append((next_label, exit_label))
1.20 +
1.21 + def drop_loop_labels(self):
1.22 + self.loop_labels.pop()
1.23 +
1.24 + def get_exception_labels(self):
1.25 + return self.exception_labels[-1]
1.26 +
1.27 + def add_exception_labels(self, handler_label, exit_label):
1.28 + self.exception_labels.append((handler_label, exit_label))
1.29 +
1.30 + def drop_exception_labels(self):
1.31 + self.exception_labels.pop()
1.32 +
1.33 def new_op(self, op):
1.34
1.35 "Add 'op' to the generated code."
1.36 @@ -236,7 +255,7 @@
1.37 self.new_op(LoadContext())
1.38 self.new_op(CheckContext())
1.39 self.new_op(JumpIfTrue(continue_label))
1.40 - self.new_op(LoadAttr(self._get_builtin("TypeError")))
1.41 + self.dispatch(compiler.ast.Name("TypeError"))
1.42 self.new_op(RaiseException())
1.43 self.set_label(continue_label)
1.44
1.45 @@ -299,6 +318,10 @@
1.46 else:
1.47 self.dispatch(arg)
1.48
1.49 + def _endCallFunc(self):
1.50 +
1.51 + "Make the invocation and tidy up afterwards."
1.52 +
1.53 self.new_op(LoadCallable()) # uses the start of the frame to get the callable
1.54 self.new_op(Jump())
1.55
1.56 @@ -383,7 +406,7 @@
1.57 def dispatch(self, node, *args):
1.58 return ASTVisitor.dispatch(self, node, *args)
1.59
1.60 - def visitAdd(self, node):
1.61 + def _visitBinary(self, node, left_method, right_method):
1.62
1.63 """
1.64 _t1 = node.left
1.65 @@ -394,6 +417,44 @@
1.66 _t2.__radd__(_t1)
1.67 """
1.68
1.69 + right_label = self.new_label()
1.70 + end_label = self.new_label()
1.71 +
1.72 + # NOTE: Decide on temporary storage access.
1.73 +
1.74 + self.dispatch(node.left)
1.75 + self.new_op(StoreTemp(1))
1.76 + self.dispatch(node.right)
1.77 + self.new_op(StoreTemp(2))
1.78 +
1.79 + # Left method.
1.80 +
1.81 + self._startCallFunc()
1.82 + self.new_op(LoadTemp(1))
1.83 + self._generateAttr(left_method, (LoadAttr, LoadAttrIndex))
1.84 + self.new_op(LoadTemp(1)) # Explicit context as first argument.
1.85 + self.new_op(LoadTemp(2))
1.86 + self._endCallFunc()
1.87 +
1.88 + self.dispatch(compiler.ast.Name("AttributeError"))
1.89 + self.new_op(CheckException())
1.90 + self.new_op(JumpIfFalse(end_label))
1.91 +
1.92 + # Right method.
1.93 +
1.94 + self.set_label(right_label)
1.95 + self._startCallFunc()
1.96 + self.new_op(LoadTemp(2))
1.97 + self._generateAttr(right_method, (LoadAttr, LoadAttrIndex))
1.98 + self.new_op(LoadTemp(2)) # Explicit context as first argument.
1.99 + self.new_op(LoadTemp(1))
1.100 + self._endCallFunc()
1.101 +
1.102 + self.set_label(end_label)
1.103 +
1.104 + def visitAdd(self, node):
1.105 + self._visitBinary(node, "__add__", "__radd__")
1.106 +
1.107 def visitAnd(self, node): pass
1.108
1.109 def visitAssert(self, node): pass
1.110 @@ -424,7 +485,7 @@
1.111 def visitBitxor(self, node): pass
1.112
1.113 def visitBreak(self, node):
1.114 - next_label, exit_label = self.loop_labels[-1]
1.115 + next_label, exit_label = self.get_loop_labels()
1.116 self.new_op(Jump(exit_label))
1.117
1.118 def visitCallFunc(self, node):
1.119 @@ -439,6 +500,7 @@
1.120 self._startCallFunc()
1.121 self.dispatch(node.node)
1.122 self._generateCallFunc(node.args, node)
1.123 + self._endCallFunc()
1.124
1.125 def visitClass(self, node):
1.126 unit = self.unit
1.127 @@ -465,7 +527,7 @@
1.128 self.new_op(LoadConst(const))
1.129
1.130 def visitContinue(self, node):
1.131 - next_label, exit_label = self.loop_labels[-1]
1.132 + next_label, exit_label = self.get_loop_labels()
1.133 self.new_op(Jump(next_label))
1.134
1.135 def visitDecorators(self, node): pass
1.136 @@ -475,7 +537,8 @@
1.137 def visitDiscard(self, node):
1.138 self.dispatch(node.expr)
1.139
1.140 - def visitDiv(self, node): pass
1.141 + def visitDiv(self, node):
1.142 + self._visitBinary(node, "__div__", "__rdiv__")
1.143
1.144 def visitEllipsis(self, node): pass
1.145
1.146 @@ -483,7 +546,8 @@
1.147
1.148 def visitExpression(self, node): pass
1.149
1.150 - def visitFloorDiv(self, node): pass
1.151 + def visitFloorDiv(self, node):
1.152 + self._visitBinary(node, "__floordiv__", "__rfloordiv__")
1.153
1.154 def visitFor(self, node):
1.155 exit_label = self.new_label()
1.156 @@ -496,6 +560,8 @@
1.157 self.dispatch(node.list)
1.158 self._generateAttr("__iter__", (LoadAttr, LoadAttrIndex))
1.159 self._generateCallFunc([], node)
1.160 + self._endCallFunc()
1.161 +
1.162 # Iterator on stack.
1.163
1.164 # In the loop...
1.165 @@ -508,10 +574,12 @@
1.166 self.new_op(Duplicate())
1.167 self._generateAttr("next", (LoadAttr, LoadAttrIndex))
1.168 self._generateCallFunc([], node)
1.169 + self._endCallFunc()
1.170
1.171 # Test for StopIteration.
1.172
1.173 - self.new_op(CheckException("StopIteration")) # NOTE: To be done properly.
1.174 + self.dispatch(compiler.ast.Name("StopIteration"))
1.175 + self.new_op(CheckException())
1.176 if node.else_ is not None:
1.177 self.new_op(JumpIfTrue(else_label))
1.178 else:
1.179 @@ -523,9 +591,9 @@
1.180
1.181 # Process the body with the current next and exit points.
1.182
1.183 - self.loop_labels.append((next_label, exit_label))
1.184 + self.add_loop_labels(next_label, exit_label)
1.185 self.dispatch(node.body)
1.186 - self.loop_labels.pop()
1.187 + self.drop_loop_labels()
1.188
1.189 # Repeat the loop.
1.190
1.191 @@ -608,12 +676,14 @@
1.192
1.193 def visitListCompIf(self, node): pass
1.194
1.195 - def visitMod(self, node): pass
1.196 + def visitMod(self, node):
1.197 + self._visitBinary(node, "__mod__", "__rmod__")
1.198
1.199 def visitModule(self, node):
1.200 self.dispatch(node.node)
1.201
1.202 - def visitMul(self, node): pass
1.203 + def visitMul(self, node):
1.204 + self._visitBinary(node, "__mul__", "__rmul__")
1.205
1.206 def visitName(self, node):
1.207 self._visitName(node, (LoadName, LoadAttr))
1.208 @@ -645,11 +715,58 @@
1.209 for n in node.nodes:
1.210 self.dispatch(n)
1.211
1.212 - def visitSub(self, node): pass
1.213 + def visitSub(self, node):
1.214 + self._visitBinary(node, "__sub__", "__rsub__")
1.215
1.216 def visitSubscript(self, node): pass
1.217
1.218 - def visitTryExcept(self, node): pass
1.219 + def visitTryExcept(self, node):
1.220 +
1.221 + """
1.222 + Enter try block.
1.223 + Dispatch to code.
1.224 +
1.225 + """
1.226 +
1.227 + exit_label = self.new_label()
1.228 + handler_label = self.new_label()
1.229 +
1.230 + self.add_exception_labels(handler_label, exit_label)
1.231 +
1.232 + self.dispatch(node.body)
1.233 + self.new_op(Jump(exit_label))
1.234 +
1.235 + self.set_label(handler_label)
1.236 + for name, assignment, handler in node.handlers:
1.237 + next_label = self.new_label()
1.238 +
1.239 + if name is not None:
1.240 + self.dispatch(name)
1.241 + self.new_op(CheckException())
1.242 + self.new_op(JumpIfFalse(next_label))
1.243 +
1.244 + if assignment is not None:
1.245 + self.dispatch(assignment)
1.246 +
1.247 + self.dispatch(handler)
1.248 + self.new_op(Jump(exit_label))
1.249 +
1.250 + self.set_label(next_label)
1.251 +
1.252 + # Unhandled exceptions.
1.253 +
1.254 + self.new_op(RaiseException())
1.255 +
1.256 + # After exception
1.257 +
1.258 + self.set_label(exit_label)
1.259 +
1.260 + # Optional else clause.
1.261 +
1.262 + if node.else_ is not None:
1.263 + self.dispatch(node.else_)
1.264 +
1.265 + self.drop_exception_labels()
1.266
1.267 def visitTryFinally(self, node): pass
1.268
1.269 @@ -671,7 +788,7 @@
1.270 else:
1.271 self.new_op(JumpIfFalse(exit_label))
1.272
1.273 - self.loop_labels.append((next_label, exit_label))
1.274 + self.add_loop_labels(next_label, exit_label)
1.275
1.276 self.dispatch(node.body)
1.277 self.new_op(Jump(next_label))
1.278 @@ -681,7 +798,7 @@
1.279 self.dispatch(node.else_)
1.280
1.281 self.set_label(exit_label)
1.282 - self.loop_labels.pop()
1.283 + self.drop_loop_labels()
1.284
1.285 def visitWith(self, node): pass
1.286