1.1 --- a/micropython/ast.py Fri Aug 22 00:50:59 2008 +0200
1.2 +++ b/micropython/ast.py Sat Aug 23 02:41:55 2008 +0200
1.3 @@ -48,7 +48,7 @@
1.4 # Instructions which affect the current value.
1.5
1.6 current_value_instructions = (LoadConst, LoadName, LoadTemp, LoadAddress, LoadAddressContext, LoadAttr, LoadAttrIndex,
1.7 - LoadCallable, LoadContext, LoadResult, LoadException, LoadBoolean, MakeObject)
1.8 + LoadCallable, LoadContext, LoadResult, LoadException, MakeObject)
1.9
1.10 def __init__(self, module, importer, optimisations=None):
1.11
1.12 @@ -295,6 +295,15 @@
1.13 self.remove_op()
1.14 self.new_op(op)
1.15
1.16 + def replace_active_value(self, op):
1.17 +
1.18 + """
1.19 + Replace the value-providing active instruction with 'op' if appropriate.
1.20 + """
1.21 +
1.22 + self.remove_active_value()
1.23 + self.new_op(op)
1.24 +
1.25 def last_op(self):
1.26
1.27 "Return the last added instruction."
1.28 @@ -345,7 +354,10 @@
1.29
1.30 def _is_simple_input(self, instruction):
1.31
1.32 - "Return whether 'instruction' provides a simple input."
1.33 + """
1.34 + Return whether 'instruction' provides a simple input (typically a load
1.35 + instruction).
1.36 + """
1.37
1.38 return isinstance(instruction, (LoadConst, LoadName, LoadTemp, LoadResult, LoadAddress, MakeObject))
1.39
1.40 @@ -357,7 +369,7 @@
1.41 StoreTemp, StoreFrame, StoreResult, StoreException, # as the value being stored
1.42 LoadAddressContext, LoadAttr, LoadAttrIndex, # as the object being referenced
1.43 StoreAttr, StoreAttrIndex, StoreCallable, # as the object being referenced
1.44 - TestIdentity, CheckSelf, # as one of the operands
1.45 + TestIdentity, TestIdentityAddress, CheckSelf, # as one of the operands
1.46 LoadContext, # as the object providing the result
1.47 JumpWithFrame # as the target
1.48 ))
1.49 @@ -635,8 +647,8 @@
1.50 # Where the last operation (defining the attribute owner) yields a
1.51 # constant...
1.52
1.53 - if self._is_constant_input(self.active):
1.54 - last = self.active
1.55 + if self._have_constant_input():
1.56 + last = self.active_value
1.57
1.58 # Get the details of the access.
1.59
1.60 @@ -673,7 +685,7 @@
1.61 # Produce a suitable instruction.
1.62
1.63 if AddressInstruction is not None:
1.64 - self.replace_op(AddressInstruction(pos))
1.65 + self.replace_active_value(AddressInstruction(pos))
1.66 else:
1.67 raise TranslateError(self.module.full_name(), node,
1.68 "Storing of class or module attribute %r via an object is not permitted." % attrname)
1.69 @@ -941,8 +953,7 @@
1.70
1.71 # Set the frame size.
1.72
1.73 - self.frame_makers[-1].attr = nargs_max
1.74 - self.frame_makers.pop()
1.75 + self._endCallFuncArgs(nargs_max)
1.76
1.77 # Or generate instructions to do this at run-time.
1.78 # NOTE: CheckFrame has to check the number of arguments and to fill in
1.79 @@ -959,8 +970,7 @@
1.80
1.81 # Set the frame size.
1.82
1.83 - self.frame_makers[-1].attr = max_pos + 1
1.84 - self.frame_makers.pop()
1.85 + self._endCallFuncArgs(max_pos + 1)
1.86
1.87 def _generateCallFuncDefaultArgs(self, target, temp, nargs_min, nargs_max, employed_positions):
1.88
1.89 @@ -995,6 +1005,13 @@
1.90 self.new_op(instruction)
1.91 self.new_op(JumpWithFrame())
1.92
1.93 + def _endCallFuncArgs(self, nargs):
1.94 +
1.95 + "Set the frame size."
1.96 +
1.97 + self.frame_makers[-1].attr = nargs
1.98 + self.frame_makers.pop()
1.99 +
1.100 def _endCallFunc(self, instruction=None, load_result=1):
1.101
1.102 "Finish the invocation and tidy up afterwards."
1.103 @@ -1123,6 +1140,7 @@
1.104
1.105 self.new_op(temp) # Explicit context as first argument.
1.106 self.new_op(StoreFrame(0))
1.107 + self._endCallFuncArgs(1)
1.108 self._doCallFunc(temp_method)
1.109 self._endCallFunc(temp_method)
1.110 self.new_op(Jump(end_label))
1.111 @@ -1238,6 +1256,7 @@
1.112 self.new_op(StoreFrame(0))
1.113 self.new_op(temp2)
1.114 self.new_op(StoreFrame(1))
1.115 + self._endCallFuncArgs(2)
1.116 self._doCallFunc(temp_method)
1.117 self._endCallFunc(temp_method)
1.118
1.119 @@ -1265,23 +1284,6 @@
1.120 self.new_op(CheckException())
1.121 self.new_op(JumpIfTrue(end_call_label))
1.122
1.123 - def _propagateAttributeError(self, node):
1.124 -
1.125 - """
1.126 - Add exception raising to the method acquisition instructions where the
1.127 - attribute access cannot be resolved at compile-time.
1.128 - """
1.129 -
1.130 - if not self._optimise_known_target():
1.131 - continue_label = self.new_label()
1.132 -
1.133 - self.load_builtin("AttributeError", node)
1.134 - self.new_op(CheckException())
1.135 - self.new_op(JumpIfFalse(continue_label))
1.136 - self.new_op(RaiseException())
1.137 -
1.138 - self.set_label(continue_label)
1.139 -
1.140 def _generateSequence(self, sequence_type, node):
1.141
1.142 "Make a sequence of 'sequence_type' for the given program 'node'."
1.143 @@ -1300,6 +1302,51 @@
1.144 self.new_op(temp)
1.145 self.discard_temp(temp)
1.146
1.147 + def _generateTestBoolean(self, node):
1.148 +
1.149 + """
1.150 + Generate a test of the boolean status of the current value for the given
1.151 + program 'node'.
1.152 + """
1.153 +
1.154 + temp = self._optimise_temp_storage()
1.155 +
1.156 + # Get method on temp.
1.157 + # NOTE: Using __bool__ instead of __nonzero__.
1.158 +
1.159 + self._generateAttr(node, "__bool__", self.attribute_load_instructions)
1.160 + temp_method = self._optimise_temp_storage()
1.161 +
1.162 + self._startCallFunc()
1.163 + self.new_op(temp)
1.164 + self.new_op(StoreFrame(0))
1.165 + self._endCallFuncArgs(1)
1.166 + self._doCallFunc(temp_method)
1.167 + self._endCallFunc(temp_method)
1.168 +
1.169 + # Convert result to boolean (a StoreBoolean operation).
1.170 +
1.171 + self.new_op(TestIdentityAddress(self.get_builtin("True", node)))
1.172 +
1.173 + def _generateLoadBoolean(self, node):
1.174 +
1.175 + """
1.176 + Generate instructions to load the appropriate value given the current
1.177 + boolean status.
1.178 + """
1.179 +
1.180 + true_label = self.new_label()
1.181 + end_label = self.new_label()
1.182 +
1.183 + self.new_op(JumpIfTrue(true_label))
1.184 + self.load_builtin("False", node)
1.185 + self.new_op(Jump(end_label))
1.186 +
1.187 + self.set_label(true_label)
1.188 + self.load_builtin("True", node)
1.189 +
1.190 + self.set_label(end_label)
1.191 +
1.192 # Concrete visitor methods.
1.193
1.194 def visitAdd(self, node):
1.195 @@ -1310,7 +1357,7 @@
1.196
1.197 for n in node.nodes[:-1]:
1.198 self.dispatch(n)
1.199 - self.new_op(TestBoolean())
1.200 + self._generateTestBoolean(n)
1.201 self.new_op(JumpIfFalse(next_label))
1.202
1.203 self.dispatch(node.nodes[-1])
1.204 @@ -1425,7 +1472,7 @@
1.205 # Generate method call using evaluated argument and next node.
1.206
1.207 self._generateBinary(node, temp1, temp2, left_method, right_method)
1.208 - self.new_op(TestBoolean())
1.209 + self._generateTestBoolean(node)
1.210
1.211 else:
1.212 # Deal with the special operators.
1.213 @@ -1447,8 +1494,6 @@
1.214 self._generateAttr(node, "__contains__", self.attribute_load_instructions)
1.215 temp_method = self._optimise_temp_storage()
1.216
1.217 - self._propagateAttributeError(node)
1.218 -
1.219 # Add arguments.
1.220 # NOTE: No support for defaults.
1.221
1.222 @@ -1456,9 +1501,10 @@
1.223 self.new_op(StoreFrame(0))
1.224 self.new_op(temp1)
1.225 self.new_op(StoreFrame(1))
1.226 + self._endCallFuncArgs(2)
1.227 self._doCallFunc(temp_method)
1.228 self._endCallFunc(temp_method)
1.229 - self.new_op(TestBoolean())
1.230 + self._generateTestBoolean(node)
1.231
1.232 if op_name.find("not") != -1:
1.233 self.new_op(InvertBoolean())
1.234 @@ -1477,7 +1523,7 @@
1.235
1.236 # Yield the appropriate value.
1.237
1.238 - self.new_op(LoadBoolean())
1.239 + self._generateLoadBoolean(node)
1.240
1.241 def visitConst(self, node):
1.242 const = self.module.constant_values[node.value]
1.243 @@ -1716,19 +1762,9 @@
1.244 true_label = self.new_label()
1.245
1.246 self.dispatch(node.expr)
1.247 - self.new_op(TestBoolean())
1.248 + self._generateTestBoolean(node.expr)
1.249 self.new_op(InvertBoolean())
1.250 - self.new_op(LoadBoolean())
1.251 -
1.252 - # The equivalent of InvertBoolean/LoadBoolean.
1.253 -
1.254 - #self.new_op(JumpIfTrue(true_label))
1.255 - #self.load_builtin("True", node)
1.256 - #self.new_op(Jump(next_label))
1.257 -
1.258 - #self.set_label(true_label)
1.259 - #self.load_builtin("False", node)
1.260 - #self.set_label(next_label)
1.261 + self._generateLoadBoolean(node)
1.262
1.263 # Prevent incorrect optimisation.
1.264
1.265 @@ -1740,7 +1776,7 @@
1.266
1.267 for n in node.nodes[:-1]:
1.268 self.dispatch(n)
1.269 - self.new_op(TestBoolean())
1.270 + self._generateTestBoolean(n)
1.271 self.new_op(JumpIfTrue(next_label))
1.272
1.273 self.dispatch(node.nodes[-1])
1.274 @@ -1773,6 +1809,7 @@
1.275 self._startCallFunc()
1.276 self.new_op(temp_arg)
1.277 self.new_op(StoreFrame(0))
1.278 + self._endCallFuncArgs(1)
1.279 self._doCallFunc(temp)
1.280 self._endCallFunc(temp)
1.281