1.1 --- a/micropython/trans.py Sun Jun 26 23:54:37 2011 +0200
1.2 +++ b/micropython/trans.py Sat Jul 02 02:41:33 2011 +0200
1.3 @@ -89,229 +89,6 @@
1.4 else:
1.5 raise TranslateError("No __builtins__ module is available for name %r." % name)
1.6
1.7 - # Code feature methods.
1.8 -
1.9 - def new_block(self):
1.10 -
1.11 - "Return a new code block."
1.12 -
1.13 - return Block()
1.14 -
1.15 - def set_block(self, block):
1.16 -
1.17 - "Add the given 'block' to the unit's list of blocks."
1.18 -
1.19 - self.optimiser.reset()
1.20 - self.blocks.append(block)
1.21 -
1.22 - def get_loop_blocks(self):
1.23 - return self.loop_blocks[-1]
1.24 -
1.25 - def add_loop_blocks(self, next_block, exit_block):
1.26 - self.loop_blocks.append((next_block, exit_block))
1.27 -
1.28 - def drop_loop_blocks(self):
1.29 - self.loop_blocks.pop()
1.30 -
1.31 - def add_exception_unit(self):
1.32 - self.exception_blocks.append([])
1.33 -
1.34 - def get_exception_blocks(self):
1.35 - return self.exception_blocks[-1][-1]
1.36 -
1.37 - def add_exception_blocks(self, handler_block, exit_block):
1.38 - self.exception_blocks[-1].append((handler_block, exit_block))
1.39 -
1.40 - def drop_exception_blocks(self):
1.41 - self.exception_blocks[-1].pop()
1.42 -
1.43 - def drop_exception_unit(self):
1.44 - self.exception_blocks.pop()
1.45 -
1.46 - # Assignment expression values.
1.47 -
1.48 - def record_value(self, immediate=1):
1.49 -
1.50 - """
1.51 - Record the current active value for an assignment. If the optional
1.52 - 'immediate' parameter if set to a false value always allocates new
1.53 - temporary storage to hold the recorded value; otherwise, the
1.54 - value-providing instruction may be replicated in order to provide the
1.55 - active value later on.
1.56 - """
1.57 -
1.58 - if immediate:
1.59 - temp = self.optimiser.optimise_temp_storage()
1.60 - else:
1.61 - temp = self.get_temp()
1.62 - self.expr_temp.append(temp)
1.63 -
1.64 - def discard_value(self):
1.65 -
1.66 - "Discard any temporary storage in use for the current assignment value."
1.67 -
1.68 - self.discard_temp(self.expr_temp.pop())
1.69 -
1.70 - def set_source(self):
1.71 -
1.72 - """
1.73 - Set the source of an assignment using the current assignment value. This
1.74 - sets the source input for the current instruction.
1.75 - """
1.76 -
1.77 - self.optimiser.set_source(self.expr_temp[-1])
1.78 -
1.79 - # Optimise away constant storage if appropriate.
1.80 -
1.81 - if self.optimiser.optimise_constant_storage():
1.82 - self.remove_op()
1.83 -
1.84 - def is_immediate_user(self, node):
1.85 -
1.86 - """
1.87 - Return whether 'node' is an immediate user of an assignment expression.
1.88 - """
1.89 -
1.90 - return isinstance(node, (compiler.ast.AssName, compiler.ast.AssAttr))
1.91 -
1.92 - def has_immediate_usage(self, nodes):
1.93 -
1.94 - """
1.95 - Return whether 'nodes' are all immediate users of an assignment expression.
1.96 - """
1.97 -
1.98 - for n in nodes:
1.99 - if not self.is_immediate_user(n):
1.100 - return 0
1.101 - return 1
1.102 -
1.103 - # Temporary storage administration.
1.104 -
1.105 - def get_temp(self):
1.106 -
1.107 - """
1.108 - Add a temporary storage instruction for the current value and return a
1.109 - sequence of access instructions.
1.110 - """
1.111 -
1.112 - position_in_frame = self.reserve_temp()
1.113 - self.new_op(StoreTemp(position_in_frame))
1.114 - return LoadTemp(position_in_frame)
1.115 -
1.116 - def reserve_temp(self, temp_position=None):
1.117 -
1.118 - """
1.119 - Reserve a new temporary storage position, or if the optional
1.120 - 'temp_position' is specified, ensure that this particular position is
1.121 - reserved.
1.122 - """
1.123 -
1.124 - if temp_position is not None:
1.125 - pass
1.126 - elif not self.temp_positions:
1.127 - temp_position = 0
1.128 - else:
1.129 - temp_position = max(self.temp_positions) + 1
1.130 -
1.131 - self.temp_positions.add(temp_position)
1.132 - self.max_temp_position = max(self.max_temp_position, temp_position)
1.133 - return self.unit.all_local_usage + temp_position # position in frame
1.134 -
1.135 - def ensure_temp(self, instruction=None):
1.136 -
1.137 - """
1.138 - Ensure that the 'instruction' is using a reserved temporary storage
1.139 - position.
1.140 - """
1.141 -
1.142 - if isinstance(instruction, LoadTemp):
1.143 - temp_position = instruction.attr - self.unit.all_local_usage
1.144 - self.reserve_temp(temp_position)
1.145 -
1.146 - def discard_temp(self, instruction=None):
1.147 -
1.148 - "Discard any temporary storage position used by 'instruction'."
1.149 -
1.150 - if isinstance(instruction, LoadTemp):
1.151 - temp_position = instruction.attr - self.unit.all_local_usage
1.152 - self.free_temp(temp_position)
1.153 -
1.154 - def free_temp(self, temp_position):
1.155 -
1.156 - "Free the temporary storage position specified by 'temp_position'."
1.157 -
1.158 - if temp_position in self.temp_positions:
1.159 - self.temp_positions.remove(temp_position)
1.160 -
1.161 - def set_frame_usage(self, node, extend):
1.162 -
1.163 - """
1.164 - Ensure that the frame usage for the unit associated with 'node' is set
1.165 - on the 'extend' instruction.
1.166 - """
1.167 -
1.168 - # Remove any ExtendFrame instructions which do nothing.
1.169 -
1.170 - if self.last_op() is extend:
1.171 - self.remove_op()
1.172 - return
1.173 -
1.174 - ntemp = self.max_temp_position + 1
1.175 - extend.attr = ntemp + node.unit.local_usage # NOTE: See get_code for similar code.
1.176 -
1.177 - # Code writing methods.
1.178 -
1.179 - def new_op(self, op):
1.180 -
1.181 - """
1.182 - Add 'op' to the generated code, returning a true value if an instruction
1.183 - was added.
1.184 - """
1.185 -
1.186 - # Optimise load operations employed by this instruction.
1.187 -
1.188 - self.optimiser.optimise_load_operations(op)
1.189 - if self.optimiser.optimise_away_no_operations(op) or self.optimiser.optimise_unused_handlers(op):
1.190 - return 0
1.191 -
1.192 - # Add the operation to the current block.
1.193 -
1.194 - self.blocks[-1].code.append(op)
1.195 - self.optimiser.set_new(op)
1.196 - return 1
1.197 -
1.198 - def remove_op(self):
1.199 -
1.200 - "Remove the last instruction."
1.201 -
1.202 - op = self.blocks[-1].code.pop()
1.203 - self.optimiser.clear_active()
1.204 -
1.205 - def replace_op(self, op):
1.206 -
1.207 - "Replace the last added instruction with 'op'."
1.208 -
1.209 - self.remove_op()
1.210 - self.new_op(op)
1.211 -
1.212 - def replace_active_value(self, op):
1.213 -
1.214 - """
1.215 - Replace the value-providing active instruction with 'op' if appropriate.
1.216 - """
1.217 -
1.218 - self.optimiser.remove_active_value()
1.219 - self.new_op(op)
1.220 -
1.221 - def last_op(self):
1.222 -
1.223 - "Return the last added instruction."
1.224 -
1.225 - try:
1.226 - return self.blocks[-1].code[-1]
1.227 - except IndexError:
1.228 - return None
1.229 -
1.230 # Common methods.
1.231
1.232 def _generateGuards(self, node):
1.233 @@ -1479,11 +1256,20 @@
1.234 for i, n in enumerate(node.nodes):
1.235 self.dispatch(n)
1.236 self.record_value()
1.237 - self.new_op(temp)
1.238 - self.new_op(StoreAttr(Attr(i + offset, None, None)))
1.239 - self.set_source()
1.240 + self._storeInSequence(temp, i, offset)
1.241 self.discard_value()
1.242
1.243 + def _storeInSequence(self, temp, i, offset=0):
1.244 +
1.245 + """
1.246 + Store the current active value in the fragment referenced by 'temp' at
1.247 + position 'i' with the given starting 'offset'.
1.248 + """
1.249 +
1.250 + self.new_op(temp)
1.251 + self.new_op(StoreAttr(Attr(i + offset, None, None)))
1.252 + self.set_source()
1.253 +
1.254 def _generateTestBoolean(self, node, temp):
1.255
1.256 """