1.1 --- a/micropython/ast.py Sat Jun 21 17:23:23 2008 +0200
1.2 +++ b/micropython/ast.py Sun Jun 22 02:20:56 2008 +0200
1.3 @@ -75,22 +75,8 @@
1.4 self.temp_position = 0
1.5 self.stack = []
1.6
1.7 - def calculate_stack_usage(self):
1.8 - max_stack_usage = 0
1.9 - stack_usage = 0
1.10 -
1.11 - for op in self.code:
1.12 -
1.13 - # Fix stack access operands.
1.14 -
1.15 - op.fix_stack(stack_usage)
1.16 -
1.17 - # Update the stack levels.
1.18 -
1.19 - stack_usage += op.stack_usage
1.20 - max_stack_usage = max(max_stack_usage, stack_usage)
1.21 -
1.22 - self.unit.stack_usage = max_stack_usage
1.23 + def __repr__(self):
1.24 + return "Translation(%r)" % self.module
1.25
1.26 def get_module_code(self):
1.27
1.28 @@ -104,7 +90,6 @@
1.29 if self.module.module is not None:
1.30 self.dispatch(self.module.module)
1.31
1.32 - self.calculate_stack_usage()
1.33 return self.code
1.34
1.35 def get_code(self, unit):
1.36 @@ -119,12 +104,8 @@
1.37 if unit.astnode is not None:
1.38 self.dispatch(unit.astnode)
1.39
1.40 - self.calculate_stack_usage()
1.41 return self.code
1.42
1.43 - def __repr__(self):
1.44 - return "Translation(%r)" % self.module
1.45 -
1.46 def get_scope(self, name):
1.47 if self.unit.has_key(name):
1.48 return "local"
1.49 @@ -133,7 +114,47 @@
1.50 else:
1.51 return "builtins"
1.52
1.53 - # Code writing methods.
1.54 + # Code feature methods.
1.55 +
1.56 + def reset_stack(self):
1.57 +
1.58 + "Reset the stack for the current unit."
1.59 +
1.60 + self.stack = []
1.61 +
1.62 + def adjust_stack(self, op):
1.63 +
1.64 + "Adjust the stack according to the effect of 'op'."
1.65 +
1.66 + position = len(self.code)
1.67 + stack_level = len(self.stack)
1.68 +
1.69 + op.fix_stack(stack_level)
1.70 + effect = op.get_effect()
1.71 +
1.72 + if effect == 1:
1.73 + self.stack.append((position, op))
1.74 + elif effect < 0:
1.75 + while effect != 0:
1.76 + self.stack.pop()
1.77 + effect += 1
1.78 +
1.79 + # Update the stack levels.
1.80 +
1.81 + self.unit.stack_usage = max(self.unit.stack_usage, stack_level)
1.82 +
1.83 + def revert_stack(self, op):
1.84 +
1.85 + "Revert the stack affected by 'op'."
1.86 +
1.87 + effect = op.get_effect()
1.88 +
1.89 + if effect > 0:
1.90 + while effect != 0:
1.91 + self.stack.pop()
1.92 + effect -= 1
1.93 + elif effect < 0:
1.94 + raise ProcessingError, "Cannot remove instructions which reduce the stack."
1.95
1.96 def new_label(self):
1.97
1.98 @@ -183,33 +204,35 @@
1.99 if isinstance(temp, LoadTemp):
1.100 self.temp_position -= 1
1.101
1.102 + # Code writing methods.
1.103 +
1.104 def new_op(self, op):
1.105
1.106 "Add 'op' to the generated code."
1.107
1.108 position = len(self.code)
1.109 self._optimise_stack_access(op)
1.110 -
1.111 - if isinstance(op, ResetStack):
1.112 - if not self.stack:
1.113 - return
1.114 - self.stack = []
1.115 + self.adjust_stack(op)
1.116
1.117 self.code.append(op)
1.118
1.119 - if op.stack_usage == 1:
1.120 - self.stack.append((position, op))
1.121 - elif op.stack_usage == -1:
1.122 - for operand in op.operands:
1.123 - if isinstance(operand, StackLoad):
1.124 - self.stack.pop()
1.125 -
1.126 def new_ops(self, ops):
1.127
1.128 - "Add 'ops' to the generated code."
1.129 + """
1.130 + Add copies of 'ops' to the generated code. This is typically used in
1.131 + connection with sequences of temporary storage instructions.
1.132 + """
1.133
1.134 for op in ops:
1.135 - self.new_op(op)
1.136 + self.new_op(op.copy())
1.137 +
1.138 + def remove_ops(self, n):
1.139 +
1.140 + "Remove the last 'n' instructions."
1.141 +
1.142 + for i in range(0, n):
1.143 + op = self.code.pop()
1.144 + self.revert_stack(op)
1.145
1.146 def replace_op(self, op):
1.147
1.148 @@ -236,21 +259,6 @@
1.149 else:
1.150 break
1.151
1.152 - def remove_ops(self, n):
1.153 -
1.154 - "Remove the last 'n' instructions."
1.155 -
1.156 - for i in range(0, n):
1.157 - op = self.code.pop()
1.158 - if op.stack_usage == 1:
1.159 - self.stack.pop()
1.160 - elif op.stack_usage < 0:
1.161 - for operand in op.operands:
1.162 - if isinstance(operand, StackLoad):
1.163 - raise ProcessingError, "Cannot remove instructions which reduce the stack."
1.164 - elif isinstance(op, ResetStack):
1.165 - raise ProcessingError, "Cannot remove instructions which reduce the stack."
1.166 -
1.167 def last_ops(self, n):
1.168
1.169 "Return the last 'n' added instructions in reverse chronological order."
1.170 @@ -547,6 +555,7 @@
1.171 self.new_op(RaiseException())
1.172 self.set_label(continue_label)
1.173
1.174 + first = 0
1.175 frame_pos += 1
1.176
1.177 # NOTE: Extra keywords are not supported.
1.178 @@ -704,7 +713,7 @@
1.179 def _have_temp_compatible_access(self):
1.180 last = self.last_op()
1.181 # NOTE: Should expand to cover LoadAttr and LoadAttrIndex, but this
1.182 - # NOTE: would require inspection of the stack operands.
1.183 + # NOTE: would require inspection of the stack operations.
1.184 return isinstance(last, (LoadName, LoadTemp, LoadAddress, LoadConst))
1.185
1.186 def _have_fixed_sources(self, access):
1.187 @@ -836,13 +845,24 @@
1.188 return 0
1.189
1.190 def _optimise_stack_access(self, instruction):
1.191 +
1.192 + """
1.193 + Optimise stack access for the given 'instruction', replacing stack
1.194 + operations with instructions directly accessing the required data.
1.195 + """
1.196 +
1.197 if self._should_optimise_stack_access():
1.198 ops = self._have_fixed_sources(instruction.stack_access)
1.199 if ops:
1.200 - #print "Optimised", instruction.operands, "->", ops
1.201 + #print "Optimised", instruction.accesses, "->", ops
1.202 for i in range(0, instruction.stack_access):
1.203 self.remove_op_using_stack()
1.204 - instruction.operands = ops
1.205 + instruction.accesses = ops
1.206 +
1.207 + # Remove the stack side-effects of these accesses.
1.208 +
1.209 + for op in ops:
1.210 + op.remove_results()
1.211
1.212 # Visitor methods.
1.213
1.214 @@ -1135,7 +1155,6 @@
1.215
1.216 def visitDiscard(self, node):
1.217 self.dispatch(node.expr)
1.218 - self.new_op(ResetStack())
1.219
1.220 def visitDiv(self, node):
1.221 self._visitBinary(node, "__div__", "__rdiv__")
1.222 @@ -1208,7 +1227,6 @@
1.223 # Pop the iterator.
1.224
1.225 self.set_label(exit_label)
1.226 - self.new_op(ResetStack())
1.227
1.228 def visitFrom(self, node): pass
1.229
1.230 @@ -1332,6 +1350,7 @@
1.231 def visitStmt(self, node):
1.232 for n in node.nodes:
1.233 self.dispatch(n)
1.234 + self.reset_stack()
1.235
1.236 def visitSub(self, node):
1.237 self._visitBinary(node, "__sub__", "__rsub__")