1.1 --- a/micropython/ast.py Sun Sep 07 18:43:40 2008 +0200
1.2 +++ b/micropython/ast.py Sun Sep 07 20:23:10 2008 +0200
1.3 @@ -93,7 +93,7 @@
1.4 a load operation from a CPU register or special memory location.
1.5 """
1.6
1.7 - return isinstance(instruction, (LoadConst, LoadName, LoadTemp, LoadResult, LoadAddress))
1.8 + return isinstance(instruction, (LoadConst, LoadName, LoadTemp, LoadResult, LoadException, LoadAddress))
1.9
1.10 def is_simple_input_user(self, instruction):
1.11
1.12 @@ -109,7 +109,7 @@
1.13 StoreAttr, StoreAttrIndex, StoreCallable, # as the object being referenced
1.14 LoadCallable,
1.15 TestIdentity, TestIdentityAddress, CheckSelf, # as one of the operands
1.16 - CheckFrame, MakeObject,
1.17 + CheckException, CheckFrame, MakeObject,
1.18 LoadContext # as the object providing the result
1.19 ))
1.20
1.21 @@ -187,7 +187,8 @@
1.22 # could be updated since first being referenced.
1.23
1.24 return isinstance(self.translation.active_value, (LoadName, LoadTemp, LoadAddress, LoadConst)) or \
1.25 - isinstance(self.translation.active_value, LoadResult) and self.translation.active_value is self.translation.active
1.26 + isinstance(self.translation.active_value, LoadResult) and self.translation.active_value is self.translation.active or \
1.27 + isinstance(self.translation.active_value, LoadException) and self.translation.active_value is self.translation.active
1.28
1.29 def have_correct_self_for_target(self, context):
1.30
1.31 @@ -2048,13 +2049,20 @@
1.32
1.33 if name is not None:
1.34 self.dispatch(name)
1.35 +
1.36 self.new_op(CheckException())
1.37 self.new_op(JumpIfFalse(next_label))
1.38
1.39 - # Handle assignment to exception variable.
1.40 -
1.41 - if assignment is not None:
1.42 - self.dispatch(assignment)
1.43 + # Handle assignment to exception variable.
1.44 +
1.45 + if assignment is not None:
1.46 + self.new_op(LoadException())
1.47 +
1.48 + # Record the value to be assigned.
1.49 +
1.50 + self.record_value()
1.51 + self.dispatch(assignment)
1.52 + self.discard_value()
1.53
1.54 # Produce the handler code, then jump to the exit.
1.55
1.56 @@ -2065,7 +2073,6 @@
1.57
1.58 # Unhandled exceptions.
1.59
1.60 - #self.new_op(LoadException())
1.61 self.new_op(RaiseException())
1.62
1.63 # Optional else clause.
2.1 --- a/micropython/rsvp.py Sun Sep 07 18:43:40 2008 +0200
2.2 +++ b/micropython/rsvp.py Sun Sep 07 20:23:10 2008 +0200
2.3 @@ -25,11 +25,15 @@
2.4 def raw(code, objtable, paramtable):
2.5 new_code = []
2.6 for item in code:
2.7 +
2.8 if isinstance(item, Attr):
2.9 new_code.append((
2.10 item.context and item.context.location,
2.11 item.value and item.value.location # no useful context is provided
2.12 ))
2.13 +
2.14 + # Using classcode, attrcode, codeaddr, codedetails, instance.
2.15 +
2.16 elif isinstance(item, Class):
2.17 # NOTE: Need initialiser details!
2.18 new_code.append((
2.19 @@ -39,14 +43,20 @@
2.20 (
2.21 len(item.get_instantiator().positional_names),
2.22 len(item.get_instantiator().defaults)
2.23 - )))
2.24 + ),
2.25 + 0
2.26 + ))
2.27 +
2.28 elif isinstance(item, Const):
2.29 # NOTE: Need class details!
2.30 new_code.append((
2.31 None, #objtable.as_list().get_code(item.full_name()),
2.32 None, #objtable.get_index(item.full_name()),
2.33 - None, None
2.34 + None,
2.35 + None,
2.36 + 1
2.37 ))
2.38 +
2.39 elif isinstance(item, Function):
2.40 # NOTE: Need class and parameter details! Should arguably be types.FunctionType.
2.41 new_code.append((
2.42 @@ -56,9 +66,13 @@
2.43 (
2.44 len(item.positional_names),
2.45 len(item.defaults)
2.46 - )))
2.47 + ),
2.48 + 0
2.49 + ))
2.50 +
2.51 else:
2.52 new_code.append(item)
2.53 +
2.54 return new_code
2.55
2.56 def name(attr):
4.1 --- a/rsvp.py Sun Sep 07 18:43:40 2008 +0200
4.2 +++ b/rsvp.py Sun Sep 07 20:23:10 2008 +0200
4.3 @@ -24,22 +24,32 @@
4.4
4.5 The execution model of the virtual processor involves the following things:
4.6
4.7 - * Memory
4.8 - * PC (program counter) stack
4.9 - * Frame stack (containing invocation frames in use and in preparation plus
4.10 - temporary storage)
4.11 - * Local frame pointer stack
4.12 + * Memory contains constants, global variable
4.13 + references and program code
4.14 +
4.15 + * PC (program counter) stack contains the return address associated
4.16 + with each function invocation
4.17 +
4.18 + * Frame stack contains invocation frames in use and in
4.19 + preparation plus temporary storage
4.20 +
4.21 + * Local frame pointer stack refers to the frames in the frame stack
4.22 +
4.23 * Invocation frame pointer stack
4.24 +
4.25 * Exception handler stack
4.26 - * Registers: current value, boolean status value, source value, result,
4.27 - current exception, current callable
4.28
4.29 -The memory contains constants, global variable references and program code.
4.30 + * Exception handler locals stack refers to the state of the local frame
4.31 + pointer stack
4.32 +
4.33 + * Exception handler PC stack refers to the state of the PC stack
4.34
4.35 -The PC stack contains the return address associated with each function
4.36 -invocation.
4.37 -
4.38 -The frame pointer stack tracks the position of frames within the frame stack.
4.39 + * Registers: current value,
4.40 + boolean status value,
4.41 + source value,
4.42 + current result,
4.43 + current exception,
4.44 + current callable
4.45 """
4.46
4.47 class IllegalInstruction(Exception):
4.48 @@ -77,7 +87,9 @@
4.49 self.frame_stack = []
4.50 self.local_sp_stack = [0]
4.51 self.invocation_sp_stack = []
4.52 - self.handler_stack = []
4.53 + self.handler_stack = [len(self.memory) - 1] # final handler is the end of the code
4.54 + self.handler_local_sp_stack = []
4.55 + self.handler_pc_stack = []
4.56
4.57 # Registers.
4.58
4.59 @@ -97,6 +109,8 @@
4.60 print "Local stack pointers", self.local_sp_stack
4.61 print "Invocation stack pointers", self.invocation_sp_stack
4.62 print "Handler stack", self.handler_stack
4.63 + print "Handler frame stack", self.handler_local_sp_stack
4.64 + print "Handler PC stack", self.handler_pc_stack
4.65 print
4.66 print "Instruction", self.instruction
4.67 print "Operand", self.operand
4.68 @@ -265,10 +279,10 @@
4.69 def MakeObject(self):
4.70 size = self.operand
4.71 context, ref = self.value
4.72 - classcode, attrcode, codeaddr, codedetails = self.load(ref)
4.73 + classcode, attrcode, codeaddr, codedetails, instance = self.load(ref)
4.74 addr = self.new(size)
4.75 # Set the header to resemble the class.
4.76 - self.save(addr, (classcode, attrcode, None, None)) # NOTE: __call__ method not yet provided.
4.77 + self.save(addr, (classcode, attrcode, None, None, 1)) # NOTE: __call__ method not yet provided.
4.78 # Introduce null context for new object.
4.79 self.value = None, addr
4.80
4.81 @@ -284,7 +298,7 @@
4.82
4.83 def LoadAttrIndex(self):
4.84 context, ref = self.value
4.85 - classcode, attrcode, codeaddr, codedetails = self.load(ref)
4.86 + classcode, attrcode, codeaddr, codedetails, instance = self.load(ref)
4.87 element = self.objlist[classcode + self.operand]
4.88 attr_index, class_attr, replace_context, offset = element
4.89 if attr_index == self.operand:
4.90 @@ -302,7 +316,7 @@
4.91
4.92 def StoreAttrIndex(self):
4.93 context, ref = self.value
4.94 - classcode, attrcode, codeaddr, codedetails = self.load(ref)
4.95 + classcode, attrcode, codeaddr, codedetails, instance = self.load(ref)
4.96 element = self.objlist[classcode + self.operand]
4.97 attr_index, class_attr, replace_context, offset = element
4.98 if attr_index == self.operand:
4.99 @@ -336,7 +350,7 @@
4.100
4.101 def StoreFrameIndex(self):
4.102 frame = self.invocation_sp_stack[-1] # different from the current frame after MakeFrame
4.103 - classcode, attrcode, codeaddr, codedetails = self.load(ref)
4.104 + classcode, attrcode, codeaddr, codedetails, instance = self.load(ref)
4.105 element = self.objlist[classcode + self.operand]
4.106 attr_index, offset = element
4.107 if attr_index == self.operand:
4.108 @@ -347,14 +361,14 @@
4.109
4.110 def LoadCallable(self):
4.111 context, ref = self.value
4.112 - classcode, attrcode, codeaddr, codedetails = self.load(ref)
4.113 + classcode, attrcode, codeaddr, codedetails, instance = self.load(ref)
4.114 self.callable = codeaddr, codedetails
4.115
4.116 def StoreCallable(self):
4.117 context, ref = self.value
4.118 # NOTE: Should improve the representation and permit direct saving.
4.119 - classcode, attrcode, codeaddr, codedetails = self.load(ref)
4.120 - self.save(ref, (classcode, attrcode) + self.callable)
4.121 + classcode, attrcode, codeaddr, codedetails, instance = self.load(ref)
4.122 + self.save(ref, (classcode, attrcode) + self.callable + (instance,))
4.123
4.124 def LoadContext(self):
4.125 context, ref = self.value
4.126 @@ -364,7 +378,7 @@
4.127 operand = self.operand
4.128 frame = self.invocation_sp_stack[-1]
4.129 context, ref = self.value
4.130 - classcode, attrcode, codeaddr, codedetails = self.load(ref)
4.131 + classcode, attrcode, codeaddr, codedetails, instance = self.load(ref)
4.132
4.133 # Support sliding of the frame to exclude any inappropriate context.
4.134
4.135 @@ -372,7 +386,8 @@
4.136 self.invocation_sp_stack[-1] += 1
4.137 operand -= 1
4.138 else:
4.139 - if contexttype == self.typetype:
4.140 + context_classcode, context_attrcode, context_codeaddr, context_codedetails, context_instance = self.load(context)
4.141 + if not context_instance:
4.142 self.invocation_sp_stack[-1] += 1
4.143 operand -= 1
4.144
4.145 @@ -386,19 +401,9 @@
4.146 context, ref = self.value
4.147 target_context, target_ref = self.source
4.148
4.149 - # Load the details of the proposed context and the target's context.
4.150 -
4.151 - classcode, attrcode, codeaddr, codedetails = self.load(ref)
4.152 - target_classcode, target_attrcode, target_codeaddr, target_codedetails = self.load(target_context)
4.153 -
4.154 - # Find the table entry for the descendant.
4.155 + # Check the details of the proposed context and the target's context.
4.156
4.157 - element = self.objlist[target_classcode + attrcode]
4.158 - attr_index, class_attr, replace_context, offset = element
4.159 - if attr_index == attrcode:
4.160 - self.status = 1
4.161 - else:
4.162 - self.status = 0
4.163 + self._CheckInstance(ref, target_context)
4.164
4.165 def JumpWithFrame(self):
4.166 codeaddr, codedetails = self.callable
4.167 @@ -437,25 +442,31 @@
4.168 return self.operand
4.169
4.170 def LoadException(self):
4.171 - self.value = self.exception
4.172 + self.value = None, self.exception
4.173
4.174 def StoreException(self):
4.175 - self.exception = self.value
4.176 + self.exception = self.value[1]
4.177
4.178 def RaiseException(self):
4.179 - return self.handler_stack.pop()
4.180 + return self.handler_stack[-1]
4.181
4.182 def PushHandler(self):
4.183 self.handler_stack.append(self.operand)
4.184 + self.handler_local_sp_stack.append(len(self.local_sp_stack))
4.185 + self.handler_pc_stack.append(len(self.pc_stack))
4.186
4.187 def PopHandler(self):
4.188 + # Reduce the local frame pointer stack to refer to the handler's frame.
4.189 + self.local_sp_stack = self.local_sp_stack[:self.handler_local_sp_stack.pop()]
4.190 + # Reduce the PC stack to discard all superfluous return addresses.
4.191 + self.pc_stack = self.pc_stack[:self.handler_pc_stack.pop()]
4.192 self.handler_stack.pop()
4.193
4.194 def CheckException(self):
4.195 - self.status = self.value[1] == self.exception
4.196 + self._CheckInstance(self.exception, self.value[1])
4.197
4.198 def TestIdentity(self):
4.199 - self.status = self.value[1] == self.source
4.200 + self.status = self.value[1] == self.source[1]
4.201
4.202 def TestIdentityAddress(self):
4.203 self.status = self.value[1] == self.operand
4.204 @@ -466,4 +477,19 @@
4.205 def InvertBoolean(self):
4.206 self.status = not self.status
4.207
4.208 + # Common implementation details.
4.209 +
4.210 + def _CheckInstance(self, ref, cls):
4.211 + classcode, attrcode, codeaddr, codedetails, instance = self.load(ref)
4.212 + target_classcode, target_attrcode, target_codeaddr, target_codedetails, target_instance = self.load(cls)
4.213 +
4.214 + # Find the table entry for the descendant.
4.215 +
4.216 + element = self.objlist[target_classcode + attrcode]
4.217 + attr_index, class_attr, replace_context, offset = element
4.218 + if attr_index == attrcode:
4.219 + self.status = 1
4.220 + else:
4.221 + self.status = 0
4.222 +
4.223 # vim: tabstop=4 expandtab shiftwidth=4