# HG changeset patch # User Paul Boddie # Date 1244397856 -7200 # Node ID 424eacd023949bf57af80772eb5577b8fb4c7087 # Parent 31c5526286ba05d9f6c4a856b384638c907f0fb3 Fixed RSVP implementations of attribute access instructions, handling empty object table entries correctly and raising attribute errors under appropriate circumstances. Fixed the test for context overriding to handle the different context type values appropriately. diff -r 31c5526286ba -r 424eacd02394 rsvp.py --- a/rsvp.py Wed Jun 03 00:48:57 2009 +0200 +++ b/rsvp.py Sun Jun 07 20:04:16 2009 +0200 @@ -459,50 +459,59 @@ context, ref = self.value data = self.load(ref) element = self.objlist[data.classcode + self.operand] - attr_index, class_attr, offset = element - if attr_index == self.operand: - if class_attr: - self.value = self.load(offset) # offset is address of class attribute - else: - self.value = self.load(ref + offset) - else: - self.exception = self._MakeObject(2, self.attr_error_instance) - return self.RaiseException() + + if element is not None: + attr_index, class_attr, offset = element + if attr_index == self.operand: + if class_attr: + self.value = self.load(offset) # offset is address of class attribute + else: + self.value = self.load(ref + offset) + return + + self.exception = self._MakeObject(2, self.attr_error_instance) + return self.RaiseException() # LoadAttrIndexContext not defined. def LoadAttrIndexContextCond(self): - context, ref = self.value - data = self.load(ref) + inst_context, inst_ref = self.value + data = self.load(inst_ref) element = self.objlist[data.classcode + self.operand] - attr_index, class_attr, offset = element - if attr_index == self.operand: - if class_attr: - loaded_context, loaded_ref = self.load(offset) # offset is address of class attribute - if data.attrcode is None: # absent attrcode == class - self.value = loaded_context, loaded_ref + + if element is not None: + attr_index, class_attr, offset = element + if attr_index == self.operand: + if class_attr: + loaded_context, loaded_ref = self.load(offset) # offset is address of class attribute + if data.attrcode is None: # absent attrcode == class + self.value = loaded_context, loaded_ref + else: + self.value = self._LoadAddressContextCond(loaded_context, loaded_ref, inst_ref) else: - self.value = self._LoadAddressContextCond(loaded_context, loaded_ref, ref) - else: - self.value = self.load(ref + offset) - else: - self.exception = self._MakeObject(2, self.attr_error_instance) - return self.RaiseException() + self.value = self.load(inst_ref + offset) + return + + self.exception = self._MakeObject(2, self.attr_error_instance) + return self.RaiseException() def StoreAttrIndex(self): context, ref = self.value data = self.load(ref) element = self.objlist[data.classcode + self.operand] - attr_index, class_attr, offset = element - if attr_index == self.operand: - if class_attr: - self.exception = self._MakeObject(2, self.type_error_instance) - return self.RaiseException() - else: - self.save(ref + offset, self.source) - else: - self.exception = self._MakeObject(2, self.attr_error_instance) - return self.RaiseException() + + if element is not None: + attr_index, class_attr, offset = element + if attr_index == self.operand: + if class_attr: + self.exception = self._MakeObject(2, self.type_error_instance) + return self.RaiseException() + else: + self.save(ref + offset, self.source) + return + + self.exception = self._MakeObject(2, self.attr_error_instance) + return self.RaiseException() # NOTE: LoadAttrIndexContext is a possibility if a particular attribute can always be overridden. @@ -524,13 +533,16 @@ frame = self.invocation_sp_stack[-1] # different from the current frame after MakeFrame data = self.load(ref) element = self.paramlist[data.funccode + self.operand] - # NOTE: Need to ensure correct positioning where a context has been generated. - param_index, offset = element - if param_index == self.operand: - self.frame_stack[frame + offset] = self.source - else: - self.exception = self._MakeObject(2, self.type_error_instance) - return self.RaiseException() + + if element is not None: + # NOTE: Need to ensure correct positioning where a context has been generated. + param_index, offset = element + if param_index == self.operand: + self.frame_stack[frame + offset] = self.source + return + + self.exception = self._MakeObject(2, self.type_error_instance) + return self.RaiseException() def LoadCallable(self): context, ref = self.value @@ -712,6 +724,7 @@ # Find the table entry for the descendant. element = self.objlist[target_data.classcode + data.attrcode] + if element is not None: attr_index, class_attr, offset = element return attr_index == data.attrcode @@ -729,7 +742,7 @@ def _LoadAddressContextCond(self, context, ref, inst_ref): # Check the instance context against the target's context. # This provides the context overriding for methods. - if context is not ReplaceableContext and self._CheckInstance(inst_ref, context): + if context is ReplaceableContext or context is not PlaceholderContext and self._CheckInstance(inst_ref, context): # Replace the context with the instance. return inst_ref, ref else: