2.1 --- a/micropython/ast.py Sat Apr 26 18:35:18 2008 +0200
2.2 +++ b/micropython/ast.py Sun Apr 27 03:11:12 2008 +0200
2.3 @@ -50,19 +50,24 @@
2.4
2.5 supported_optimisations = ["constant_storage", "known_target", "self_access"]
2.6
2.7 - def __init__(self, module, objtable, paramtable, builtins=None, optimisations=None):
2.8 + def __init__(self, module, importer, optimisations=None):
2.9
2.10 """
2.11 - Initialise the translation with an inspected 'module' and an attribute
2.12 - table 'objtable' and parameter table 'paramtable'.
2.13 + Initialise the translation with an inspected 'module', the 'importer'
2.14 + and optional 'optimisations'. See the 'supported_optimisations'
2.15 + attribute of this class for permitted values.
2.16 """
2.17
2.18 ASTVisitor.__init__(self)
2.19 self.visitor = self
2.20 self.module = module
2.21 - self.objtable = objtable
2.22 - self.paramtable = paramtable
2.23 - self.builtins = builtins
2.24 +
2.25 + # Global program dependencies.
2.26 +
2.27 + self.importer = importer
2.28 + self.objtable = self.importer.get_object_table()
2.29 + self.paramtable = self.importer.get_parameter_table()
2.30 + self.builtins = self.importer.modules.get("__builtins__")
2.31
2.32 # Desired optimisations.
2.33
2.34 @@ -79,10 +84,26 @@
2.35 self.loop_labels = []
2.36 self.exception_labels = []
2.37
2.38 - # The code itself.
2.39 + # The code itself. This is limited to the code for a particular block
2.40 + # being processed.
2.41
2.42 self.code = None
2.43
2.44 + def calculate_stack_usage(self):
2.45 + max_stack_usage = 0
2.46 + max_stack_temp_usage = 0
2.47 + stack_usage = 0
2.48 + stack_temp_usage = 0
2.49 +
2.50 + for op in self.code:
2.51 + stack_usage += op.stack_usage
2.52 + stack_temp_usage += op.stack_temp_usage
2.53 + max_stack_usage = max(max_stack_usage, stack_usage)
2.54 + max_stack_temp_usage = max(max_stack_temp_usage, stack_temp_usage)
2.55 +
2.56 + self.unit.stack_usage = max_stack_usage
2.57 + self.unit.stack_temp_usage = max_stack_temp_usage
2.58 +
2.59 def get_module_code(self):
2.60
2.61 "Return the top-level module code."
2.62 @@ -91,6 +112,7 @@
2.63 self.code = []
2.64 if self.module.module is not None:
2.65 self.dispatch(self.module.module)
2.66 + self.calculate_stack_usage()
2.67 return self.code
2.68
2.69 def get_code(self, unit):
2.70 @@ -101,6 +123,7 @@
2.71 self.code = []
2.72 if unit.node is not None:
2.73 self.dispatch(unit.node)
2.74 + self.calculate_stack_usage()
2.75 return self.code
2.76
2.77 def get_default_code(self, unit):
2.78 @@ -111,7 +134,7 @@
2.79 for attr, default in zip(unit.default_attrs, unit.defaults):
2.80 self.dispatch(default)
2.81 self.new_op(LoadConst(unit))
2.82 - self.new_op(StoreAttr(attr))
2.83 + self.new_op(StoreAddress(attr))
2.84 return self.code
2.85
2.86 def __repr__(self):
2.87 @@ -217,7 +240,7 @@
2.88 Generate code for the access to 'attrname' using the given 'classes'.
2.89 """
2.90
2.91 - AttrInstruction, AttrIndexInstruction = classes
2.92 + AddressInstruction, AttrInstruction, AttrIndexInstruction = classes
2.93 # NOTE: Only simple cases are used for optimisations.
2.94
2.95 last = self.last_op()
2.96 @@ -229,7 +252,7 @@
2.97
2.98 # Optimise away the constant storage if appropriate.
2.99
2.100 - if self._optimise_constant_storage(AttrInstruction, 1):
2.101 + if self._optimise_constant_storage(AddressInstruction, 1):
2.102 return
2.103
2.104 # Get the details of the access.
2.105 @@ -249,7 +272,10 @@
2.106 raise TranslateError(self.module.full_name(), node,
2.107 "No attribute entry exists for name %r in target %r." % (attrname, target_name))
2.108
2.109 - self.replace_op(AttrInstruction(pos))
2.110 + if isinstance(target, micropython.inspect.Instance):
2.111 + self.replace_op(AttrInstruction(pos))
2.112 + else:
2.113 + self.replace_op(AddressInstruction(pos))
2.114
2.115 # Where the last operation involves the special 'self' name, check to
2.116 # see if the attribute is acceptably positioned and produce a direct
2.117 @@ -476,7 +502,7 @@
2.118 'classes', and using the given 'node' as the source of the access.
2.119 """
2.120
2.121 - NameInstruction, AttrInstruction = classes
2.122 + NameInstruction, AddressInstruction = classes
2.123
2.124 if self._optimise_constant_storage(NameInstruction, 0):
2.125 return
2.126 @@ -486,21 +512,21 @@
2.127 if isinstance(unit, micropython.inspect.Function):
2.128 self.new_op(NameInstruction(unit.all_locals()[name]))
2.129 elif isinstance(unit, micropython.inspect.Class):
2.130 - self.new_op(AttrInstruction(unit.all_class_attributes()[name]))
2.131 + self.new_op(AddressInstruction(unit.all_class_attributes()[name]))
2.132 elif isinstance(unit, micropython.inspect.Module):
2.133 - self.new_op(AttrInstruction(unit.module_attributes()[name]))
2.134 + self.new_op(AddressInstruction(unit.module_attributes()[name]))
2.135 else:
2.136 raise TranslateError(self.module.full_name(), node, "Program unit %r has no local %r." % (unit, name))
2.137
2.138 elif scope == "global":
2.139 globals = self.module.module_attributes()
2.140 if globals.has_key(name):
2.141 - self.new_op(AttrInstruction(globals[name]))
2.142 + self.new_op(AddressInstruction(globals[name]))
2.143 else:
2.144 raise TranslateError(self.module.full_name(), node, "Module %r has no attribute %r." % (self.module, name))
2.145
2.146 else:
2.147 - self.new_op(AttrInstruction(self._get_builtin(name, node)))
2.148 + self.new_op(AddressInstruction(self._get_builtin(name, node)))
2.149
2.150 def _get_builtin(self, name, node):
2.151 if self.builtins is not None:
2.152 @@ -546,7 +572,7 @@
2.153 """
2.154
2.155 if self._should_optimise_constant_storage() and \
2.156 - instruction in (StoreAttr, StoreName) and \
2.157 + instruction in (StoreAddress, StoreName) and \
2.158 self._have_constant_input(n) and \
2.159 (n == 0 or self._have_constant_input(n-1)):
2.160
2.161 @@ -633,7 +659,7 @@
2.162
2.163 self._startCallFunc()
2.164 self.new_op(LoadTemp(1))
2.165 - self._generateAttr(node, left_method, (LoadAttr, LoadAttrIndex))
2.166 + self._generateAttr(node, left_method, (LoadAddress, LoadAttr, LoadAttrIndex))
2.167 self.new_op(LoadTemp(1)) # Explicit context as first argument.
2.168 self.new_op(LoadTemp(2))
2.169 self._endCallFunc()
2.170 @@ -647,7 +673,7 @@
2.171 self.set_label(right_label)
2.172 self._startCallFunc()
2.173 self.new_op(LoadTemp(2))
2.174 - self._generateAttr(node, right_method, (LoadAttr, LoadAttrIndex))
2.175 + self._generateAttr(node, right_method, (LoadAddress, LoadAttr, LoadAttrIndex))
2.176 self.new_op(LoadTemp(2)) # Explicit context as first argument.
2.177 self.new_op(LoadTemp(1))
2.178 self._endCallFunc()
2.179 @@ -667,12 +693,12 @@
2.180 self.dispatch(n)
2.181
2.182 def visitAssAttr(self, node):
2.183 - self._visitAttr(node, (StoreAttr, StoreAttrIndex))
2.184 + self._visitAttr(node, (StoreAddress, StoreAttr, StoreAttrIndex))
2.185
2.186 def visitAssList(self, node): pass
2.187
2.188 def visitAssName(self, node):
2.189 - self._visitName(node, (StoreName, StoreAttr))
2.190 + self._visitName(node, (StoreName, StoreAddress))
2.191
2.192 visitAssTuple = visitAssList
2.193
2.194 @@ -760,7 +786,7 @@
2.195
2.196 self._startCallFunc()
2.197 self.dispatch(node.list)
2.198 - self._generateAttr(node, "__iter__", (LoadAttr, LoadAttrIndex))
2.199 + self._generateAttr(node, "__iter__", (LoadAddress, LoadAttr, LoadAttrIndex))
2.200 self._generateCallFunc([], node)
2.201 self._endCallFunc()
2.202
2.203 @@ -774,7 +800,7 @@
2.204
2.205 self._startCallFunc()
2.206 self.new_op(Duplicate())
2.207 - self._generateAttr(node, "next", (LoadAttr, LoadAttrIndex))
2.208 + self._generateAttr(node, "next", (LoadAddress, LoadAttr, LoadAttrIndex))
2.209 self._generateCallFunc([], node)
2.210 self._endCallFunc()
2.211
2.212 @@ -820,7 +846,7 @@
2.213
2.214 if self.unit is not node.unit:
2.215 self.new_op(LoadConst(node.unit))
2.216 - self._visitName(node, (StoreName, StoreAttr))
2.217 + self._visitName(node, (StoreName, StoreAddress))
2.218
2.219 # Visiting of the code occurs when get_code is invoked on this node.
2.220
2.221 @@ -839,7 +865,7 @@
2.222 def visitGenExprInner(self, node): pass
2.223
2.224 def visitGetattr(self, node):
2.225 - self._visitAttr(node, (LoadAttr, LoadAttrIndex))
2.226 + self._visitAttr(node, (LoadAddress, LoadAttr, LoadAttrIndex))
2.227
2.228 def visitGlobal(self, node): pass
2.229
2.230 @@ -890,7 +916,7 @@
2.231 self._visitBinary(node, "__mul__", "__rmul__")
2.232
2.233 def visitName(self, node):
2.234 - self._visitName(node, (LoadName, LoadAttr))
2.235 + self._visitName(node, (LoadName, LoadAddress))
2.236
2.237 def visitNot(self, node): pass
2.238
4.1 --- a/micropython/rsvp.py Sat Apr 26 18:35:18 2008 +0200
4.2 +++ b/micropython/rsvp.py Sun Apr 27 03:11:12 2008 +0200
4.3 @@ -25,6 +25,9 @@
4.4
4.5 "A generic instruction."
4.6
4.7 + stack_usage = 0
4.8 + stack_temp_usage = 0
4.9 +
4.10 def __init__(self, attr=None):
4.11 self.attr = attr
4.12
4.13 @@ -85,48 +88,86 @@
4.14
4.15 Immediate = ImmediateInstruction
4.16
4.17 +# Mix-in classes for stack effects.
4.18 +
4.19 +class StackAdd:
4.20 +
4.21 + """
4.22 + Indicate that the stack must grow to accommodate the result of this
4.23 + instruction.
4.24 + """
4.25 +
4.26 + stack_usage = 1
4.27 +
4.28 +class StackRemove:
4.29 +
4.30 + "Indicate that the stack must shrink as an effect of this instruction."
4.31 +
4.32 + stack_usage = -1
4.33 +
4.34 +class StackRemove2:
4.35 +
4.36 + "Indicate that the stack must shrink as an effect of this instruction."
4.37 +
4.38 + stack_usage = -2
4.39 +
4.40 +class TempAdd:
4.41 +
4.42 + "Indicate that one more temporary storage location is now required."
4.43 +
4.44 + stack_temp_usage = 1
4.45 +
4.46 +class TempRemove:
4.47 +
4.48 + "Indicate that one fewer temporary storage location is now required."
4.49 +
4.50 + stack_temp_usage = -1
4.51 +
4.52 # Instructions operating on the value stack.
4.53
4.54 -class LoadConst(Address): "Load the constant from the specified location."
4.55 -class Duplicate(Instruction): "Duplicate the top of stack."
4.56 -class Pop(Instruction): "Pop the top of stack."
4.57 +class LoadConst(StackAdd, Address): "Load the constant from the specified location."
4.58 +class Duplicate(StackAdd, Instruction): "Duplicate the top of the stack."
4.59 +class Pop(StackRemove, Immediate): "Pop entries from the top of the stack."
4.60
4.61 # Access within an invocation frame.
4.62
4.63 -class LoadName(SR): "Load the object from the given local attribute/variable."
4.64 -class StoreName(SR): "Store the object in the given local attribute/variable."
4.65 -class LoadTemp(SR): "Load the object from the given temporary location."
4.66 -class StoreTemp(SR): "Store the object in the given temporary location."
4.67 +class LoadName(StackAdd, SR): "Load the object from the given local attribute/variable."
4.68 +class StoreName(StackRemove, SR): "Store the object in the given local attribute/variable."
4.69 +class LoadTemp(TempAdd, SR): "Load the object from the given temporary location."
4.70 +class StoreTemp(SR): "Store the object in the given temporary location."
4.71
4.72 # Access to address-relative data.
4.73
4.74 -class MakeObject(Instruction): "Make a new object."
4.75 -# ... DropObject not defined: Assume garbage collection.
4.76 -class LoadAttr(AR): "Load the object from the given attribute."
4.77 -class StoreAttr(AR): "Store an object in the given attribute."
4.78 -class LoadAttrIndex(Immediate): "Load the object for the attribute with the given index."
4.79 -class StoreAttrIndex(Immediate): "Store an object in the attribute with the given index."
4.80 +class MakeObject(StackAdd, Instruction): "Make a new object."
4.81 +# ... DropObject not defined: Assume garbage collection.
4.82 +class LoadAttr(AR): "Load the object from the given attribute."
4.83 +class StoreAttr(StackRemove2, AR): "Store an object in the given attribute."
4.84 +class LoadAttrIndex(Immediate): "Load the object for the attribute with the given index."
4.85 +class StoreAttrIndex(StackRemove2, Immediate): "Store an object in the attribute with the given index."
4.86 +class LoadAddress(StackAdd, AR): "Load the object from the given fixed attribute address."
4.87 +class StoreAddress(StackRemove, AR): "Store an object in the given fixed attribute address."
4.88
4.89 # Access to invocation frames in preparation.
4.90
4.91 -class MakeFrame(Instruction): "Make a new invocation frame."
4.92 -class ReserveFrame(Immediate): "Reserve the given number of entries for the invocation frame."
4.93 -class DropFrame(Instruction): "Drop an invocation frame."
4.94 -class StoreFrame(Instruction): "Store an argument at the given frame location."
4.95 -class StoreFrameIndex(Immediate): "Store an argument for the parameter with the given index."
4.96 -class CheckFrame(Instruction): "Check the invocation frame for the target."
4.97 -class JumpWithFrame(Instruction): "Jump, adopting the invocation frame."
4.98 +class MakeFrame(Instruction): "Make a new invocation frame."
4.99 +class ReserveFrame(Immediate): "Reserve the given number of entries for the invocation frame."
4.100 +class DropFrame(Instruction): "Drop an invocation frame."
4.101 +class StoreFrame(StackRemove, Instruction): "Store an argument at the given frame location."
4.102 +class StoreFrameIndex(StackRemove, Immediate): "Store an argument for the parameter with the given index."
4.103 +class CheckFrame(Instruction): "Check the invocation frame for the target."
4.104 +class JumpWithFrame(Instruction): "Jump, adopting the invocation frame."
4.105
4.106 # Invocation-related instructions.
4.107
4.108 -class Jump(Instruction): "Jump unconditionally."
4.109 -class JumpIfFalse(Instruction): "Jump if the last evaluation gave a false result."
4.110 -class JumpIfTrue(Instruction): "Jump if the last evaluation gave a true result."
4.111 -class LoadCallable(Instruction): "Load the target of an invocation."
4.112 -class LoadContext(Instruction): "Load the context of an invocation."
4.113 -class CheckContext(Instruction): "Check the context of an invocation against the target, potentially discarding the context."
4.114 -class RaiseException(Instruction): "Raise an exception."
4.115 -class Return(Instruction): "Return a value from a subprogram."
4.116 -class CheckException(Instruction): "Check the raised exception against another."
4.117 +class Jump(Instruction): "Jump unconditionally."
4.118 +class JumpIfFalse(Instruction): "Jump if the last evaluation gave a false result."
4.119 +class JumpIfTrue(Instruction): "Jump if the last evaluation gave a true result."
4.120 +class LoadCallable(Instruction): "Load the target of an invocation."
4.121 +class LoadContext(Instruction): "Load the context of an invocation."
4.122 +class CheckContext(Instruction): """Check the context of an invocation against the target,
4.123 + potentially discarding the context."""
4.124 +class RaiseException(Instruction): "Raise an exception."
4.125 +class Return(Instruction): "Return a value from a subprogram."
4.126 +class CheckException(Instruction): "Check the raised exception against another."
4.127
4.128 # vim: tabstop=4 expandtab shiftwidth=4