micropython

Change of micropython/ast.py

129:146c1f0da0d1
micropython/ast.py
     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