1.1 --- a/micropython/ast.py Sat Apr 26 18:35:18 2008 +0200
1.2 +++ b/micropython/ast.py Sun Apr 27 03:11:12 2008 +0200
1.3 @@ -50,19 +50,24 @@
1.4
1.5 supported_optimisations = ["constant_storage", "known_target", "self_access"]
1.6
1.7 - def __init__(self, module, objtable, paramtable, builtins=None, optimisations=None):
1.8 + def __init__(self, module, importer, optimisations=None):
1.9
1.10 """
1.11 - Initialise the translation with an inspected 'module' and an attribute
1.12 - table 'objtable' and parameter table 'paramtable'.
1.13 + Initialise the translation with an inspected 'module', the 'importer'
1.14 + and optional 'optimisations'. See the 'supported_optimisations'
1.15 + attribute of this class for permitted values.
1.16 """
1.17
1.18 ASTVisitor.__init__(self)
1.19 self.visitor = self
1.20 self.module = module
1.21 - self.objtable = objtable
1.22 - self.paramtable = paramtable
1.23 - self.builtins = builtins
1.24 +
1.25 + # Global program dependencies.
1.26 +
1.27 + self.importer = importer
1.28 + self.objtable = self.importer.get_object_table()
1.29 + self.paramtable = self.importer.get_parameter_table()
1.30 + self.builtins = self.importer.modules.get("__builtins__")
1.31
1.32 # Desired optimisations.
1.33
1.34 @@ -79,10 +84,26 @@
1.35 self.loop_labels = []
1.36 self.exception_labels = []
1.37
1.38 - # The code itself.
1.39 + # The code itself. This is limited to the code for a particular block
1.40 + # being processed.
1.41
1.42 self.code = None
1.43
1.44 + def calculate_stack_usage(self):
1.45 + max_stack_usage = 0
1.46 + max_stack_temp_usage = 0
1.47 + stack_usage = 0
1.48 + stack_temp_usage = 0
1.49 +
1.50 + for op in self.code:
1.51 + stack_usage += op.stack_usage
1.52 + stack_temp_usage += op.stack_temp_usage
1.53 + max_stack_usage = max(max_stack_usage, stack_usage)
1.54 + max_stack_temp_usage = max(max_stack_temp_usage, stack_temp_usage)
1.55 +
1.56 + self.unit.stack_usage = max_stack_usage
1.57 + self.unit.stack_temp_usage = max_stack_temp_usage
1.58 +
1.59 def get_module_code(self):
1.60
1.61 "Return the top-level module code."
1.62 @@ -91,6 +112,7 @@
1.63 self.code = []
1.64 if self.module.module is not None:
1.65 self.dispatch(self.module.module)
1.66 + self.calculate_stack_usage()
1.67 return self.code
1.68
1.69 def get_code(self, unit):
1.70 @@ -101,6 +123,7 @@
1.71 self.code = []
1.72 if unit.node is not None:
1.73 self.dispatch(unit.node)
1.74 + self.calculate_stack_usage()
1.75 return self.code
1.76
1.77 def get_default_code(self, unit):
1.78 @@ -111,7 +134,7 @@
1.79 for attr, default in zip(unit.default_attrs, unit.defaults):
1.80 self.dispatch(default)
1.81 self.new_op(LoadConst(unit))
1.82 - self.new_op(StoreAttr(attr))
1.83 + self.new_op(StoreAddress(attr))
1.84 return self.code
1.85
1.86 def __repr__(self):
1.87 @@ -217,7 +240,7 @@
1.88 Generate code for the access to 'attrname' using the given 'classes'.
1.89 """
1.90
1.91 - AttrInstruction, AttrIndexInstruction = classes
1.92 + AddressInstruction, AttrInstruction, AttrIndexInstruction = classes
1.93 # NOTE: Only simple cases are used for optimisations.
1.94
1.95 last = self.last_op()
1.96 @@ -229,7 +252,7 @@
1.97
1.98 # Optimise away the constant storage if appropriate.
1.99
1.100 - if self._optimise_constant_storage(AttrInstruction, 1):
1.101 + if self._optimise_constant_storage(AddressInstruction, 1):
1.102 return
1.103
1.104 # Get the details of the access.
1.105 @@ -249,7 +272,10 @@
1.106 raise TranslateError(self.module.full_name(), node,
1.107 "No attribute entry exists for name %r in target %r." % (attrname, target_name))
1.108
1.109 - self.replace_op(AttrInstruction(pos))
1.110 + if isinstance(target, micropython.inspect.Instance):
1.111 + self.replace_op(AttrInstruction(pos))
1.112 + else:
1.113 + self.replace_op(AddressInstruction(pos))
1.114
1.115 # Where the last operation involves the special 'self' name, check to
1.116 # see if the attribute is acceptably positioned and produce a direct
1.117 @@ -476,7 +502,7 @@
1.118 'classes', and using the given 'node' as the source of the access.
1.119 """
1.120
1.121 - NameInstruction, AttrInstruction = classes
1.122 + NameInstruction, AddressInstruction = classes
1.123
1.124 if self._optimise_constant_storage(NameInstruction, 0):
1.125 return
1.126 @@ -486,21 +512,21 @@
1.127 if isinstance(unit, micropython.inspect.Function):
1.128 self.new_op(NameInstruction(unit.all_locals()[name]))
1.129 elif isinstance(unit, micropython.inspect.Class):
1.130 - self.new_op(AttrInstruction(unit.all_class_attributes()[name]))
1.131 + self.new_op(AddressInstruction(unit.all_class_attributes()[name]))
1.132 elif isinstance(unit, micropython.inspect.Module):
1.133 - self.new_op(AttrInstruction(unit.module_attributes()[name]))
1.134 + self.new_op(AddressInstruction(unit.module_attributes()[name]))
1.135 else:
1.136 raise TranslateError(self.module.full_name(), node, "Program unit %r has no local %r." % (unit, name))
1.137
1.138 elif scope == "global":
1.139 globals = self.module.module_attributes()
1.140 if globals.has_key(name):
1.141 - self.new_op(AttrInstruction(globals[name]))
1.142 + self.new_op(AddressInstruction(globals[name]))
1.143 else:
1.144 raise TranslateError(self.module.full_name(), node, "Module %r has no attribute %r." % (self.module, name))
1.145
1.146 else:
1.147 - self.new_op(AttrInstruction(self._get_builtin(name, node)))
1.148 + self.new_op(AddressInstruction(self._get_builtin(name, node)))
1.149
1.150 def _get_builtin(self, name, node):
1.151 if self.builtins is not None:
1.152 @@ -546,7 +572,7 @@
1.153 """
1.154
1.155 if self._should_optimise_constant_storage() and \
1.156 - instruction in (StoreAttr, StoreName) and \
1.157 + instruction in (StoreAddress, StoreName) and \
1.158 self._have_constant_input(n) and \
1.159 (n == 0 or self._have_constant_input(n-1)):
1.160
1.161 @@ -633,7 +659,7 @@
1.162
1.163 self._startCallFunc()
1.164 self.new_op(LoadTemp(1))
1.165 - self._generateAttr(node, left_method, (LoadAttr, LoadAttrIndex))
1.166 + self._generateAttr(node, left_method, (LoadAddress, LoadAttr, LoadAttrIndex))
1.167 self.new_op(LoadTemp(1)) # Explicit context as first argument.
1.168 self.new_op(LoadTemp(2))
1.169 self._endCallFunc()
1.170 @@ -647,7 +673,7 @@
1.171 self.set_label(right_label)
1.172 self._startCallFunc()
1.173 self.new_op(LoadTemp(2))
1.174 - self._generateAttr(node, right_method, (LoadAttr, LoadAttrIndex))
1.175 + self._generateAttr(node, right_method, (LoadAddress, LoadAttr, LoadAttrIndex))
1.176 self.new_op(LoadTemp(2)) # Explicit context as first argument.
1.177 self.new_op(LoadTemp(1))
1.178 self._endCallFunc()
1.179 @@ -667,12 +693,12 @@
1.180 self.dispatch(n)
1.181
1.182 def visitAssAttr(self, node):
1.183 - self._visitAttr(node, (StoreAttr, StoreAttrIndex))
1.184 + self._visitAttr(node, (StoreAddress, StoreAttr, StoreAttrIndex))
1.185
1.186 def visitAssList(self, node): pass
1.187
1.188 def visitAssName(self, node):
1.189 - self._visitName(node, (StoreName, StoreAttr))
1.190 + self._visitName(node, (StoreName, StoreAddress))
1.191
1.192 visitAssTuple = visitAssList
1.193
1.194 @@ -760,7 +786,7 @@
1.195
1.196 self._startCallFunc()
1.197 self.dispatch(node.list)
1.198 - self._generateAttr(node, "__iter__", (LoadAttr, LoadAttrIndex))
1.199 + self._generateAttr(node, "__iter__", (LoadAddress, LoadAttr, LoadAttrIndex))
1.200 self._generateCallFunc([], node)
1.201 self._endCallFunc()
1.202
1.203 @@ -774,7 +800,7 @@
1.204
1.205 self._startCallFunc()
1.206 self.new_op(Duplicate())
1.207 - self._generateAttr(node, "next", (LoadAttr, LoadAttrIndex))
1.208 + self._generateAttr(node, "next", (LoadAddress, LoadAttr, LoadAttrIndex))
1.209 self._generateCallFunc([], node)
1.210 self._endCallFunc()
1.211
1.212 @@ -820,7 +846,7 @@
1.213
1.214 if self.unit is not node.unit:
1.215 self.new_op(LoadConst(node.unit))
1.216 - self._visitName(node, (StoreName, StoreAttr))
1.217 + self._visitName(node, (StoreName, StoreAddress))
1.218
1.219 # Visiting of the code occurs when get_code is invoked on this node.
1.220
1.221 @@ -839,7 +865,7 @@
1.222 def visitGenExprInner(self, node): pass
1.223
1.224 def visitGetattr(self, node):
1.225 - self._visitAttr(node, (LoadAttr, LoadAttrIndex))
1.226 + self._visitAttr(node, (LoadAddress, LoadAttr, LoadAttrIndex))
1.227
1.228 def visitGlobal(self, node): pass
1.229
1.230 @@ -890,7 +916,7 @@
1.231 self._visitBinary(node, "__mul__", "__rmul__")
1.232
1.233 def visitName(self, node):
1.234 - self._visitName(node, (LoadName, LoadAttr))
1.235 + self._visitName(node, (LoadName, LoadAddress))
1.236
1.237 def visitNot(self, node): pass
1.238