micropython

Change of rsvp.py

145:7bdf1b4636b8
rsvp.py
     1.1 --- a/rsvp.py	Sun Sep 07 18:43:40 2008 +0200
     1.2 +++ b/rsvp.py	Sun Sep 07 20:23:10 2008 +0200
     1.3 @@ -24,22 +24,32 @@
     1.4  
     1.5  The execution model of the virtual processor involves the following things:
     1.6  
     1.7 -  * Memory
     1.8 -  * PC (program counter) stack
     1.9 -  * Frame stack (containing invocation frames in use and in preparation plus
    1.10 -                temporary storage)
    1.11 -  * Local frame pointer stack
    1.12 +  * Memory                          contains constants, global variable
    1.13 +                                    references and program code
    1.14 +
    1.15 +  * PC (program counter) stack      contains the return address associated
    1.16 +                                    with each function invocation
    1.17 +
    1.18 +  * Frame stack                     contains invocation frames in use and in
    1.19 +                                    preparation plus temporary storage
    1.20 +
    1.21 +  * Local frame pointer stack       refers to the frames in the frame stack
    1.22 +
    1.23    * Invocation frame pointer stack
    1.24 +
    1.25    * Exception handler stack
    1.26 -  * Registers: current value, boolean status value, source value, result,
    1.27 -               current exception, current callable
    1.28  
    1.29 -The memory contains constants, global variable references and program code.
    1.30 +  * Exception handler locals stack  refers to the state of the local frame
    1.31 +                                    pointer stack
    1.32 +
    1.33 +  * Exception handler PC stack      refers to the state of the PC stack
    1.34  
    1.35 -The PC stack contains the return address associated with each function
    1.36 -invocation.
    1.37 -
    1.38 -The frame pointer stack tracks the position of frames within the frame stack.
    1.39 +  * Registers: current value,
    1.40 +               boolean status value,
    1.41 +               source value,
    1.42 +               current result,
    1.43 +               current exception,
    1.44 +               current callable
    1.45  """
    1.46  
    1.47  class IllegalInstruction(Exception):
    1.48 @@ -77,7 +87,9 @@
    1.49          self.frame_stack = []
    1.50          self.local_sp_stack = [0]
    1.51          self.invocation_sp_stack = []
    1.52 -        self.handler_stack = []
    1.53 +        self.handler_stack = [len(self.memory) - 1] # final handler is the end of the code
    1.54 +        self.handler_local_sp_stack = []
    1.55 +        self.handler_pc_stack = []
    1.56  
    1.57          # Registers.
    1.58  
    1.59 @@ -97,6 +109,8 @@
    1.60          print "Local stack pointers", self.local_sp_stack
    1.61          print "Invocation stack pointers", self.invocation_sp_stack
    1.62          print "Handler stack", self.handler_stack
    1.63 +        print "Handler frame stack", self.handler_local_sp_stack
    1.64 +        print "Handler PC stack", self.handler_pc_stack
    1.65          print
    1.66          print "Instruction", self.instruction
    1.67          print "Operand", self.operand
    1.68 @@ -265,10 +279,10 @@
    1.69      def MakeObject(self):
    1.70          size = self.operand
    1.71          context, ref = self.value
    1.72 -        classcode, attrcode, codeaddr, codedetails = self.load(ref)
    1.73 +        classcode, attrcode, codeaddr, codedetails, instance = self.load(ref)
    1.74          addr = self.new(size)
    1.75          # Set the header to resemble the class.
    1.76 -        self.save(addr, (classcode, attrcode, None, None)) # NOTE: __call__ method not yet provided.
    1.77 +        self.save(addr, (classcode, attrcode, None, None, 1)) # NOTE: __call__ method not yet provided.
    1.78          # Introduce null context for new object.
    1.79          self.value = None, addr
    1.80  
    1.81 @@ -284,7 +298,7 @@
    1.82  
    1.83      def LoadAttrIndex(self):
    1.84          context, ref = self.value
    1.85 -        classcode, attrcode, codeaddr, codedetails = self.load(ref)
    1.86 +        classcode, attrcode, codeaddr, codedetails, instance = self.load(ref)
    1.87          element = self.objlist[classcode + self.operand]
    1.88          attr_index, class_attr, replace_context, offset = element
    1.89          if attr_index == self.operand:
    1.90 @@ -302,7 +316,7 @@
    1.91  
    1.92      def StoreAttrIndex(self):
    1.93          context, ref = self.value
    1.94 -        classcode, attrcode, codeaddr, codedetails = self.load(ref)
    1.95 +        classcode, attrcode, codeaddr, codedetails, instance = self.load(ref)
    1.96          element = self.objlist[classcode + self.operand]
    1.97          attr_index, class_attr, replace_context, offset = element
    1.98          if attr_index == self.operand:
    1.99 @@ -336,7 +350,7 @@
   1.100  
   1.101      def StoreFrameIndex(self):
   1.102          frame = self.invocation_sp_stack[-1] # different from the current frame after MakeFrame
   1.103 -        classcode, attrcode, codeaddr, codedetails = self.load(ref)
   1.104 +        classcode, attrcode, codeaddr, codedetails, instance = self.load(ref)
   1.105          element = self.objlist[classcode + self.operand]
   1.106          attr_index, offset = element
   1.107          if attr_index == self.operand:
   1.108 @@ -347,14 +361,14 @@
   1.109  
   1.110      def LoadCallable(self):
   1.111          context, ref = self.value
   1.112 -        classcode, attrcode, codeaddr, codedetails = self.load(ref)
   1.113 +        classcode, attrcode, codeaddr, codedetails, instance = self.load(ref)
   1.114          self.callable = codeaddr, codedetails
   1.115  
   1.116      def StoreCallable(self):
   1.117          context, ref = self.value
   1.118          # NOTE: Should improve the representation and permit direct saving.
   1.119 -        classcode, attrcode, codeaddr, codedetails = self.load(ref)
   1.120 -        self.save(ref, (classcode, attrcode) + self.callable)
   1.121 +        classcode, attrcode, codeaddr, codedetails, instance = self.load(ref)
   1.122 +        self.save(ref, (classcode, attrcode) + self.callable + (instance,))
   1.123  
   1.124      def LoadContext(self):
   1.125          context, ref = self.value
   1.126 @@ -364,7 +378,7 @@
   1.127          operand = self.operand
   1.128          frame = self.invocation_sp_stack[-1]
   1.129          context, ref = self.value
   1.130 -        classcode, attrcode, codeaddr, codedetails = self.load(ref)
   1.131 +        classcode, attrcode, codeaddr, codedetails, instance = self.load(ref)
   1.132  
   1.133          # Support sliding of the frame to exclude any inappropriate context.
   1.134  
   1.135 @@ -372,7 +386,8 @@
   1.136              self.invocation_sp_stack[-1] += 1
   1.137              operand -= 1
   1.138          else:
   1.139 -            if contexttype == self.typetype:
   1.140 +            context_classcode, context_attrcode, context_codeaddr, context_codedetails, context_instance = self.load(context)
   1.141 +            if not context_instance:
   1.142                  self.invocation_sp_stack[-1] += 1
   1.143                  operand -= 1
   1.144  
   1.145 @@ -386,19 +401,9 @@
   1.146          context, ref = self.value
   1.147          target_context, target_ref = self.source
   1.148  
   1.149 -        # Load the details of the proposed context and the target's context.
   1.150 -
   1.151 -        classcode, attrcode, codeaddr, codedetails = self.load(ref)
   1.152 -        target_classcode, target_attrcode, target_codeaddr, target_codedetails = self.load(target_context)
   1.153 -
   1.154 -        # Find the table entry for the descendant.
   1.155 +        # Check the details of the proposed context and the target's context.
   1.156  
   1.157 -        element = self.objlist[target_classcode + attrcode]
   1.158 -        attr_index, class_attr, replace_context, offset = element
   1.159 -        if attr_index == attrcode:
   1.160 -            self.status = 1
   1.161 -        else:
   1.162 -            self.status = 0
   1.163 +        self._CheckInstance(ref, target_context)
   1.164  
   1.165      def JumpWithFrame(self):
   1.166          codeaddr, codedetails = self.callable
   1.167 @@ -437,25 +442,31 @@
   1.168              return self.operand
   1.169  
   1.170      def LoadException(self):
   1.171 -        self.value = self.exception
   1.172 +        self.value = None, self.exception
   1.173  
   1.174      def StoreException(self):
   1.175 -        self.exception = self.value
   1.176 +        self.exception = self.value[1]
   1.177  
   1.178      def RaiseException(self):
   1.179 -        return self.handler_stack.pop()
   1.180 +        return self.handler_stack[-1]
   1.181  
   1.182      def PushHandler(self):
   1.183          self.handler_stack.append(self.operand)
   1.184 +        self.handler_local_sp_stack.append(len(self.local_sp_stack))
   1.185 +        self.handler_pc_stack.append(len(self.pc_stack))
   1.186  
   1.187      def PopHandler(self):
   1.188 +        # Reduce the local frame pointer stack to refer to the handler's frame.
   1.189 +        self.local_sp_stack = self.local_sp_stack[:self.handler_local_sp_stack.pop()]
   1.190 +        # Reduce the PC stack to discard all superfluous return addresses.
   1.191 +        self.pc_stack = self.pc_stack[:self.handler_pc_stack.pop()]
   1.192          self.handler_stack.pop()
   1.193  
   1.194      def CheckException(self):
   1.195 -        self.status = self.value[1] == self.exception
   1.196 +        self._CheckInstance(self.exception, self.value[1])
   1.197  
   1.198      def TestIdentity(self):
   1.199 -        self.status = self.value[1] == self.source
   1.200 +        self.status = self.value[1] == self.source[1]
   1.201  
   1.202      def TestIdentityAddress(self):
   1.203          self.status = self.value[1] == self.operand
   1.204 @@ -466,4 +477,19 @@
   1.205      def InvertBoolean(self):
   1.206          self.status = not self.status
   1.207  
   1.208 +    # Common implementation details.
   1.209 +
   1.210 +    def _CheckInstance(self, ref, cls):
   1.211 +        classcode, attrcode, codeaddr, codedetails, instance = self.load(ref)
   1.212 +        target_classcode, target_attrcode, target_codeaddr, target_codedetails, target_instance = self.load(cls)
   1.213 +
   1.214 +        # Find the table entry for the descendant.
   1.215 +
   1.216 +        element = self.objlist[target_classcode + attrcode]
   1.217 +        attr_index, class_attr, replace_context, offset = element
   1.218 +        if attr_index == attrcode:
   1.219 +            self.status = 1
   1.220 +        else:
   1.221 +            self.status = 0
   1.222 +
   1.223  # vim: tabstop=4 expandtab shiftwidth=4