# HG changeset patch # User Paul Boddie # Date 1209323155 -7200 # Node ID d4884c5a16e970e3ce145758d8547fc419ddb084 # Parent 221517a873b36ddd1611ff7eb3526d9c5d1691c6 Changed the accounting of temporary storage locations so that instructions can be generated referring to specific locations. Fixed default parameter value code generation, moving the generation inside the Translation class handler for Function nodes. Added a test of operators. diff -r 221517a873b3 -r d4884c5a16e9 micropython/__init__.py --- a/micropython/__init__.py Sun Apr 27 03:11:12 2008 +0200 +++ b/micropython/__init__.py Sun Apr 27 21:05:55 2008 +0200 @@ -187,12 +187,6 @@ image += code pos += len(code) - # Generate the default initialisation code. - - code = trans.get_default_code(obj) - image += code - pos += len(code) - # Remember the position of the module code. module.code_location = pos diff -r 221517a873b3 -r d4884c5a16e9 micropython/ast.py --- a/micropython/ast.py Sun Apr 27 03:11:12 2008 +0200 +++ b/micropython/ast.py Sun Apr 27 21:05:55 2008 +0200 @@ -88,21 +88,17 @@ # being processed. self.code = None + self.temp_position = 0 def calculate_stack_usage(self): max_stack_usage = 0 - max_stack_temp_usage = 0 stack_usage = 0 - stack_temp_usage = 0 for op in self.code: stack_usage += op.stack_usage - stack_temp_usage += op.stack_temp_usage max_stack_usage = max(max_stack_usage, stack_usage) - max_stack_temp_usage = max(max_stack_temp_usage, stack_temp_usage) self.unit.stack_usage = max_stack_usage - self.unit.stack_temp_usage = max_stack_temp_usage def get_module_code(self): @@ -110,8 +106,11 @@ self.unit = self.module self.code = [] + self.temp_position = self.unit.stack_local_usage + if self.module.module is not None: self.dispatch(self.module.module) + self.calculate_stack_usage() return self.code @@ -121,22 +120,14 @@ self.unit = unit self.code = [] + self.temp_position = self.unit.stack_local_usage + if unit.node is not None: self.dispatch(unit.node) + self.calculate_stack_usage() return self.code - def get_default_code(self, unit): - - "Return the code for the defaults in the given 'unit'." - - self.code = [] - for attr, default in zip(unit.default_attrs, unit.defaults): - self.dispatch(default) - self.new_op(LoadConst(unit)) - self.new_op(StoreAddress(attr)) - return self.code - def __repr__(self): return "Translation(%r)" % self.module @@ -187,6 +178,15 @@ def drop_exception_labels(self): self.exception_labels.pop() + def reserve_temp(self, n): + temp_position = self.temp_position + self.temp_position += n + self.unit.stack_temp_usage = max(self.unit.stack_temp_usage, self.temp_position) + return temp_position + + def discard_temp(self, n): + self.temp_position -= n + def new_op(self, op): "Add 'op' to the generated code." @@ -241,7 +241,6 @@ """ AddressInstruction, AttrInstruction, AttrIndexInstruction = classes - # NOTE: Only simple cases are used for optimisations. last = self.last_op() @@ -550,7 +549,7 @@ def _have_constant_input(self, n): last = self.last_ops(n+1) - return len(last) > n and (isinstance(last[n], LoadAttr) and last[n].attr.assignments == 1 or + return len(last) > n and (isinstance(last[n], LoadAddress) and last[n].attr.assignments == 1 or isinstance(last[n], LoadConst)) def _have_known_target(self): @@ -650,18 +649,20 @@ # NOTE: Decide on temporary storage access. + temp_position = self.reserve_temp(2) + self.dispatch(node.left) - self.new_op(StoreTemp(1)) + self.new_op(StoreTemp(temp_position)) self.dispatch(node.right) - self.new_op(StoreTemp(2)) + self.new_op(StoreTemp(temp_position + 1)) # Left method. self._startCallFunc() - self.new_op(LoadTemp(1)) + self.new_op(LoadTemp(temp_position)) self._generateAttr(node, left_method, (LoadAddress, LoadAttr, LoadAttrIndex)) - self.new_op(LoadTemp(1)) # Explicit context as first argument. - self.new_op(LoadTemp(2)) + self.new_op(LoadTemp(temp_position)) # Explicit context as first argument. + self.new_op(LoadTemp(temp_position + 1)) self._endCallFunc() self.dispatch(compiler.ast.Name("AttributeError")) @@ -672,14 +673,16 @@ self.set_label(right_label) self._startCallFunc() - self.new_op(LoadTemp(2)) + self.new_op(LoadTemp(temp_position + 1)) self._generateAttr(node, right_method, (LoadAddress, LoadAttr, LoadAttrIndex)) - self.new_op(LoadTemp(2)) # Explicit context as first argument. - self.new_op(LoadTemp(1)) + self.new_op(LoadTemp(temp_position + 1)) # Explicit context as first argument. + self.new_op(LoadTemp(temp_position)) self._endCallFunc() self.set_label(end_label) + self.discard_temp(2) + def visitAdd(self, node): self._visitBinary(node, "__add__", "__radd__") @@ -848,6 +851,12 @@ self.new_op(LoadConst(node.unit)) self._visitName(node, (StoreName, StoreAddress)) + # Generate the default initialisation code. + + for attr, default in zip(node.unit.default_attrs, node.unit.defaults): + self.dispatch(default) + self.new_op(StoreAddress(attr)) + # Visiting of the code occurs when get_code is invoked on this node. else: diff -r 221517a873b3 -r d4884c5a16e9 micropython/inspect.py --- a/micropython/inspect.py Sun Apr 27 03:11:12 2008 +0200 +++ b/micropython/inspect.py Sun Apr 27 21:05:55 2008 +0200 @@ -324,8 +324,9 @@ # Program-related details. - self.stack_usage = None - self.stack_temp_usage = None + self.stack_usage = 0 + self.stack_temp_usage = 0 + self.stack_local_usage = 0 def __repr__(self): if self.location is not None: @@ -628,8 +629,9 @@ # Program-related details. - self.stack_usage = None - self.stack_temp_usage = None + self.stack_usage = 0 + self.stack_temp_usage = 0 + self.stack_local_usage = 0 def _add_parameters(self, argnames): for name in argnames: @@ -723,10 +725,14 @@ if i is not None: j = i - for i, attr in enumerate(self.locals().values()): - attr.position = i + j + else: + j = 0 - # NOTE: May also have temporary variables. + i = -1 + for i, attr in enumerate(self.locals().values()): + attr.position = i + j + + self.stack_local_usage = i + 1 def function_from_method(self): @@ -798,8 +804,9 @@ # Program-related details. - self.stack_usage = None - self.stack_temp_usage = None + self.stack_usage = 0 + self.stack_temp_usage = 0 + self.stack_local_usage = 0 def full_name(self): return self.name diff -r 221517a873b3 -r d4884c5a16e9 micropython/rsvp.py --- a/micropython/rsvp.py Sun Apr 27 03:11:12 2008 +0200 +++ b/micropython/rsvp.py Sun Apr 27 21:05:55 2008 +0200 @@ -26,7 +26,6 @@ "A generic instruction." stack_usage = 0 - stack_temp_usage = 0 def __init__(self, attr=None): self.attr = attr @@ -111,18 +110,6 @@ stack_usage = -2 -class TempAdd: - - "Indicate that one more temporary storage location is now required." - - stack_temp_usage = 1 - -class TempRemove: - - "Indicate that one fewer temporary storage location is now required." - - stack_temp_usage = -1 - # Instructions operating on the value stack. class LoadConst(StackAdd, Address): "Load the constant from the specified location." @@ -133,8 +120,8 @@ class LoadName(StackAdd, SR): "Load the object from the given local attribute/variable." class StoreName(StackRemove, SR): "Store the object in the given local attribute/variable." -class LoadTemp(TempAdd, SR): "Load the object from the given temporary location." -class StoreTemp(SR): "Store the object in the given temporary location." +class LoadTemp(Immediate): "Load the object from the given temporary location." +class StoreTemp(Immediate): "Store the object in the given temporary location." # Access to address-relative data. diff -r 221517a873b3 -r d4884c5a16e9 tests/op_add.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/op_add.py Sun Apr 27 21:05:55 2008 +0200 @@ -0,0 +1,10 @@ +#!/usr/bin/env python + +def f(a, b, c=a+b): + return a + b + +a = 1 +b = 2 +c = a + b + +# vim: tabstop=4 expandtab shiftwidth=4