# HG changeset patch # User Paul Boddie # Date 1220565860 -7200 # Node ID 29103989ca365cd0f8c7d4970cb71ba5ecfe7090 # Parent 4c95794770e60f83af3c84b5ad9d7bbe761313f9 Added the final Return instruction to generated images. Fixed the For node processing to store assigned values before visiting assignment nodes. Changed source processing to not use temporary storage optimisations, since the conditions for such optimisations are not met in general when processing assignments. Adopted a list to hold sources (assignment expression values), since list and tuple assignment act on a hierarchy of such values. Added elementary support and tests for list assignment. diff -r 4c95794770e6 -r 29103989ca36 micropython/__init__.py --- a/micropython/__init__.py Thu Sep 04 19:44:39 2008 +0200 +++ b/micropython/__init__.py Fri Sep 05 00:04:20 2008 +0200 @@ -142,6 +142,8 @@ const.location = pos image.append(const) + last_module = self.modules_ordered[-1] + for module in self.modules_ordered: if not with_builtins and module.name == "__builtins__": @@ -229,10 +231,12 @@ # Append the module top-level code to the image. - code = trans.get_module_code() + code = trans.get_module_code(final=(module is last_module)) image += code pos += len(code) + # Remember the generated code and the location of the first instruction. + self.code = image self.code_location = self.modules["__main__"].code_location return image diff -r 4c95794770e6 -r 29103989ca36 micropython/ast.py --- a/micropython/ast.py Thu Sep 04 19:44:39 2008 +0200 +++ b/micropython/ast.py Fri Sep 05 00:04:20 2008 +0200 @@ -87,7 +87,7 @@ # The temporary storage used by the current assignment expression. - self.expr_temp = None + self.expr_temp = [] # Wiring within the code. @@ -108,9 +108,12 @@ def __repr__(self): return "Translation(%r)" % self.module - def get_module_code(self): - - "Return the top-level module code." + def get_module_code(self, final=0): + + """ + Return the top-level module code including finalising code if 'final' is + set to a true value. + """ self.unit = self.module self.code = [] @@ -120,6 +123,11 @@ if self.module.module is not None: self.dispatch(self.module.module) + # Finish off the translated program if appropriate. + + if final: + self.new_op(Return()) + self.unit.temp_usage = self.max_temp_position + 1 return self.code @@ -268,17 +276,16 @@ # Assignment expression values. def record_value(self): - self.expr_temp = self._optimise_temp_storage() + self.expr_temp.append(self.get_temp()) self.active_source = self.active def discard_value(self): - self.discard_temp(self.expr_temp) - self.expr_temp = None + self.discard_temp(self.expr_temp.pop()) self.active_source = None def set_source(self): if self.active is not None: - self.active.source = self.expr_temp + self.active.source = self.expr_temp[-1] # Optimise away constant storage if appropriate. @@ -301,7 +308,7 @@ if not self.temp_positions: temp_position = 0 else: - temp_position = max(self.temp_positions) + temp_position = max(self.temp_positions) + 1 self.temp_positions.add(temp_position) self.max_temp_position = max(self.max_temp_position, temp_position) return self.unit.all_local_usage + temp_position # position in frame @@ -1509,23 +1516,37 @@ self.record_value() for n in node.nodes: - self.dispatch(n) + self.dispatch(n, 1) self.discard_value() - def visitAssAttr(self, node): + def visitAssAttr(self, node, top_level=0): self._visitAttr(node, self.attribute_store_instructions) self.set_source() - def visitAssList(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "AssList") - - def visitAssName(self, node): + def visitAssList(self, node, top_level=1): + for i, n in enumerate(node.nodes): + self._startCallFunc() + self.new_op(self.expr_temp[-1]) + self._generateAttr(node, "__getitem__", self.attribute_load_instructions) + temp, target = self._generateCallFunc([compiler.ast.Const(i)], node) + self._doCallFunc(temp, target) + self._endCallFunc(temp, target) + + # Provide a different source value. + + self.record_value() + self.dispatch(n, 0) + self.discard_value() + + def visitAssName(self, node, top_level=1): # Optimise away intermediate source storage. - no_source = self._optimise_source_storage() + if top_level: + no_source = self._optimise_source_storage() self._visitName(node, self.name_store_instructions) - if not no_source: + if not top_level or not no_source: self.set_source() visitAssTuple = visitAssList @@ -1727,6 +1748,10 @@ self._doCallFunc(temp, target) self._endCallFunc(temp, target) + # Record the value to be assigned. + + self.record_value() + # Test for StopIteration. self.load_builtin("StopIteration", node) @@ -1739,6 +1764,7 @@ # Assign to the target. self.dispatch(node.assign) + self.discard_value() # Process the body with the current next and exit points. diff -r 4c95794770e6 -r 29103989ca36 micropython/inspect.py --- a/micropython/inspect.py Thu Sep 04 19:44:39 2008 +0200 +++ b/micropython/inspect.py Fri Sep 05 00:04:20 2008 +0200 @@ -329,8 +329,9 @@ return None def visitAssList(self, node): - for n in node.nodes: + for i, n in enumerate(node.nodes): self.dispatch(n) + self._make_constant(i) # for __getitem__(i) at run-time return None def visitAssName(self, node): diff -r 4c95794770e6 -r 29103989ca36 tests/list_assign.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/list_assign.py Fri Sep 05 00:04:20 2008 +0200 @@ -0,0 +1,6 @@ +#!/usr/bin/env python + +[a, b, c] = [1, 2, 3] +[x, y, z] = list((9, 8, 7)) + +# vim: tabstop=4 expandtab shiftwidth=4 diff -r 4c95794770e6 -r 29103989ca36 tests/list_assign2.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/list_assign2.py Fri Sep 05 00:04:20 2008 +0200 @@ -0,0 +1,5 @@ +#!/usr/bin/env python + +[d, [e, f], g] = [4, [5, 6], 7] + +# vim: tabstop=4 expandtab shiftwidth=4