1.1 --- a/micropython/ast.py Sun Sep 28 19:59:32 2008 +0200
1.2 +++ b/micropython/ast.py Sun Sep 28 21:27:01 2008 +0200
1.3 @@ -79,18 +79,33 @@
1.4 self.loop_labels = []
1.5 self.exception_labels = []
1.6
1.7 - # The code itself. This is limited to the code for a particular block
1.8 - # being processed. Also retained is information about temporary values
1.9 - # and instructions which construct frames.
1.10 -
1.11 - self.code = None
1.12 - self.temp_positions = set()
1.13 - self.max_temp_position = -1
1.14 - self.frame_makers = []
1.15 + self.reset()
1.16
1.17 def __repr__(self):
1.18 return "Translation(%r)" % self.module
1.19
1.20 + def reset(self):
1.21 +
1.22 + "Reset the state of the translator."
1.23 +
1.24 + # The code itself. This is limited to the code for a particular block
1.25 + # being processed.
1.26 +
1.27 + self.code = []
1.28 +
1.29 + # Information about temporary values.
1.30 +
1.31 + self.temp_positions = set()
1.32 + self.max_temp_position = -1
1.33 +
1.34 + # Information about instructions which construct frames.
1.35 +
1.36 + self.frame_makers = []
1.37 +
1.38 + # Optimiser state must be reset for each unit.
1.39 +
1.40 + self.optimiser.reset()
1.41 +
1.42 def get_module_code(self, final=0):
1.43
1.44 """
1.45 @@ -99,9 +114,7 @@
1.46 """
1.47
1.48 self.unit = self.module
1.49 - self.code = []
1.50 - self.temp_positions = set()
1.51 - self.max_temp_position = -1
1.52 + self.reset()
1.53
1.54 if self.module.module is not None:
1.55 self.dispatch(self.module.module)
1.56 @@ -119,9 +132,7 @@
1.57 "Return the code for the given 'unit'."
1.58
1.59 self.unit = unit
1.60 - self.code = []
1.61 - self.temp_positions = set()
1.62 - self.max_temp_position = -1
1.63 + self.reset()
1.64
1.65 if unit.astnode is not None:
1.66 self.dispatch(unit.astnode)
1.67 @@ -134,9 +145,7 @@
1.68 "Return the code for the given class 'cls'."
1.69
1.70 self.unit = cls.get_instantiator()
1.71 - self.code = []
1.72 - self.temp_positions = set()
1.73 - self.max_temp_position = -1
1.74 + self.reset()
1.75
1.76 init_method = cls.get_init_method()
1.77
1.78 @@ -200,6 +209,9 @@
1.79 self.new_op(LoadAddress(self.get_builtin(name, node)))
1.80
1.81 def get_builtin_class(self, name, node):
1.82 +
1.83 + "Return the built-in class with the given 'name' for the given 'node'."
1.84 +
1.85 return self.get_builtin(name, node).value
1.86
1.87 def get_builtin(self, name, node):
1.88 @@ -259,6 +271,15 @@
1.89 # Assignment expression values.
1.90
1.91 def record_value(self, immediate=1):
1.92 +
1.93 + """
1.94 + Record the current active value for an assignment. If the optional
1.95 + 'immediate' parameter if set to a false value always allocates new
1.96 + temporary storage to hold the recorded value; otherwise, the
1.97 + value-providing instruction may be replicated in order to provide the
1.98 + active value later on.
1.99 + """
1.100 +
1.101 if immediate:
1.102 temp = self.optimiser.optimise_temp_storage()
1.103 else:
1.104 @@ -266,14 +287,21 @@
1.105 self.expr_temp.append(temp)
1.106
1.107 def discard_value(self):
1.108 +
1.109 + "Discard any temporary storage in use for the current assignment value."
1.110 +
1.111 self.discard_temp(self.expr_temp.pop())
1.112
1.113 def set_source(self):
1.114 +
1.115 + "Set the source of an assignment using the current assignment value."
1.116 +
1.117 self.optimiser.set_source(self.expr_temp[-1])
1.118
1.119 # Optimise away constant storage if appropriate.
1.120
1.121 - self.optimiser.optimise_constant_storage()
1.122 + if self.optimiser.optimise_constant_storage():
1.123 + self.remove_op()
1.124
1.125 # Temporary storage administration.
1.126
1.127 @@ -429,13 +457,49 @@
1.128 # see if the attribute is acceptably positioned and produce a direct
1.129 # access to the attribute.
1.130
1.131 - elif self.optimiser.optimise_self_access(attrname, (AddressInstruction, AddressContextInstruction, AttrInstruction), node):
1.132 + elif self.optimiser.optimise_self_access(self.unit, attrname):
1.133 +
1.134 + # Either generate an instruction operating on an instance attribute.
1.135 +
1.136 + try:
1.137 + attr = self.unit.parent.instance_attributes()[attrname]
1.138 + self.new_op(AttrInstruction(attr))
1.139 +
1.140 + # Or generate an instruction operating on a class attribute.
1.141 +
1.142 + except KeyError:
1.143 + attr = self.unit.parent.all_attributes()[attrname]
1.144 +
1.145 + # Switch the context if the class attribute is compatible with
1.146 + # the instance.
1.147 +
1.148 + if attr.defined_within_hierarchy():
1.149 +
1.150 + # Only permit loading (not storing) of class attributes via self.
1.151 +
1.152 + if AddressContextInstruction is not None:
1.153 + self.new_op(AddressContextInstruction(attr))
1.154 + else:
1.155 + raise TranslateError(self.module.full_name(), node,
1.156 + "Storing of class attribute %r via self not permitted." % attrname)
1.157 +
1.158 + # Preserve the context if the class attribute comes from an
1.159 + # incompatible class.
1.160 +
1.161 + else:
1.162 + if AddressInstruction is not None:
1.163 + self.new_op(AddressInstruction(attr))
1.164 + else:
1.165 + raise TranslateError(self.module.full_name(), node,
1.166 + "Storing of class attribute %r via self not permitted." % attrname)
1.167 +
1.168 return
1.169
1.170 # Otherwise, perform a normal operation.
1.171
1.172 try:
1.173 index = self.objtable.get_index(attrname)
1.174 +
1.175 except self.objtable.TableError:
1.176 raise TranslateError(self.module.full_name(), node,
1.177 "No attribute entry exists for name %r." % attrname)
1.178 @@ -1749,12 +1813,26 @@
1.179 def visitSlice(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Slice")
1.180
1.181 def visitStmt(self, node):
1.182 +
1.183 + "Process the collection of statements provided by 'node'."
1.184 +
1.185 for n in node.nodes:
1.186 +
1.187 + # Process the statement.
1.188 +
1.189 self.dispatch(n)
1.190 +
1.191 + # Discard temporary storage.
1.192 +
1.193 if self.temp_positions:
1.194 #print "Had temp", self.temp_positions
1.195 self.temp_positions = set()
1.196
1.197 + # Prevent incorrect optimisation by resetting the optimiser after
1.198 + # each statement.
1.199 +
1.200 + self.optimiser.reset()
1.201 +
1.202 def visitSub(self, node):
1.203 self._visitBinary(node, "__sub__", "__rsub__")
1.204
1.205 @@ -1856,10 +1934,6 @@
1.206 self.set_label(exit_label)
1.207 self.drop_loop_labels()
1.208
1.209 - # Prevent incorrect optimisation.
1.210 -
1.211 - self.optimiser.reset()
1.212 -
1.213 def visitWith(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "With")
1.214
1.215 def visitYield(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Yield")