1.1 --- a/TO_DO.txt Mon Sep 27 23:30:55 2010 +0200
1.2 +++ b/TO_DO.txt Mon Nov 01 01:22:44 2010 +0100
1.3 @@ -1,10 +1,5 @@
1.4 -Support slicing. This is difficult because __getitem__ has to handle integers and slice
1.5 -objects differently. One could either just try and iterate over the argument and then
1.6 -catch the AttributeError for integers, or one could test the instances first.
1.7 -
1.8 -Support isinstance. Like slicing, the problem is dealing with the class or tuple input
1.9 -to the function. A strict tuple check is permissible according to the CPython behaviour,
1.10 -but an iterable would be more elegant (as would *args).
1.11 +Consider attribute assignment observations, along with the possibility of class attribute
1.12 +assignment.
1.13
1.14 Local assignment detection plus frame re-use. Example: slice.__init__ calls
1.15 xrange.__init__ with the same arguments which are unchanged in xrange.__init__. There is
2.1 --- a/lib/builtins.py Mon Sep 27 23:30:55 2010 +0200
2.2 +++ b/lib/builtins.py Mon Nov 01 01:22:44 2010 +0100
2.3 @@ -173,12 +173,20 @@
2.4 self._elements = None
2.5
2.6 def __getitem__(self, index):
2.7 - # Note usage.
2.8 - IndexError
2.9 +
2.10 + "Return the item or slice specified by 'index'."
2.11 +
2.12 + return _getitem(self, index)
2.13
2.14 def __contains__(self, value): pass
2.15 def __setitem__(self, index, value): pass
2.16 - def __getslice__(self, start, end=None): pass
2.17 +
2.18 + def __getslice__(self, start, end=None):
2.19 +
2.20 + "Return a slice starting from 'start', with the optional 'end'."
2.21 +
2.22 + return _getslice(self, start, end)
2.23 +
2.24 def __setslice__(self, start, end, slice): pass
2.25 def append(self, value): pass
2.26
2.27 @@ -202,6 +210,10 @@
2.28
2.29 return listiterator(self)
2.30
2.31 + # Special implementation methods.
2.32 +
2.33 + def __get_single_item__(self, index): pass
2.34 +
2.35 class listiterator(object):
2.36
2.37 "Implementation of listiterator."
2.38 @@ -270,10 +282,17 @@
2.39 def __init__(self, args): pass
2.40
2.41 def __getitem__(self, index):
2.42 - # Note usage.
2.43 - IndexError
2.44 +
2.45 + "Return the item or slice specified by 'index'."
2.46 +
2.47 + return _getitem(self, index)
2.48
2.49 - def __getslice__(self, start, end=None): pass
2.50 + def __getslice__(self, start, end=None):
2.51 +
2.52 + "Return a slice starting from 'start', with the optional 'end'."
2.53 +
2.54 + return tuple(_getslice(self, start, end))
2.55 +
2.56 def __len__(self): pass
2.57 def __add__(self, other): pass
2.58 def __str__(self): pass
2.59 @@ -285,6 +304,10 @@
2.60
2.61 return listiterator(self)
2.62
2.63 + # Special implementation methods.
2.64 +
2.65 + def __get_single_item__(self, index): pass
2.66 +
2.67 class unicode(basestring):
2.68 pass
2.69
2.70 @@ -435,7 +458,10 @@
2.71 either a class or a tuple of classes.
2.72 """
2.73
2.74 + # NOTE: CPython insists on tuples, but any sequence might be considered
2.75 + # NOTE: acceptable.
2.76 # NOTE: tuple.__class__ is tuple in micropython!
2.77 +
2.78 if cls_or_tuple is not tuple and cls_or_tuple.__class__ is tuple:
2.79 for cls in cls_or_tuple:
2.80 if _isinstance(obj, cls):
2.81 @@ -444,8 +470,6 @@
2.82 else:
2.83 return _isinstance(obj, cls_or_tuple)
2.84
2.85 -def _isinstance(obj, cls): pass
2.86 -
2.87 def issubclass(obj, cls_or_tuple): pass
2.88
2.89 def iter(collection):
2.90 @@ -511,6 +535,81 @@
2.91 def vars(obj=None): pass
2.92 def zip(*args): pass
2.93
2.94 +# Utility functions.
2.95 +
2.96 +def _get_absolute_index(index, length):
2.97 +
2.98 + """
2.99 + Return the absolute index for 'index' given a collection having the
2.100 + specified 'length'.
2.101 + """
2.102 +
2.103 + if index < 0:
2.104 + return length + index
2.105 + else:
2.106 + return index
2.107 +
2.108 +def _normalise_index(index, length):
2.109 +
2.110 + "Normalise 'index' for a collection having the specified 'length'."
2.111 +
2.112 + return _min(length, _max(0, _get_absolute_index(index, length)))
2.113 +
2.114 +def _max(x, y):
2.115 +
2.116 + "Return the maximum of 'x' and 'y'."
2.117 +
2.118 + if x >= y:
2.119 + return x
2.120 + else:
2.121 + return y
2.122 +
2.123 +def _min(x, y):
2.124 +
2.125 + "Return the minimum of 'x' and 'y'."
2.126 +
2.127 + if x <= y:
2.128 + return x
2.129 + else:
2.130 + return y
2.131 +
2.132 +def _getitem(seq, index):
2.133 +
2.134 + "Return the item or slice specified by 'index'."
2.135 +
2.136 + if isinstance(index, int):
2.137 + return seq.__get_single_item__(index)
2.138 + elif isinstance(index, slice):
2.139 + return seq.__getslice__(index.start, index.end)
2.140 + else:
2.141 + raise TypeError
2.142 +
2.143 +def _getslice(seq, start, end=None):
2.144 +
2.145 + "Return a slice starting from 'start', with the optional 'end'."
2.146 +
2.147 + length = len(seq)
2.148 +
2.149 + if start is None:
2.150 + start = 0
2.151 + else:
2.152 + start = _normalise_index(start, length)
2.153 +
2.154 + if end is None:
2.155 + end = length
2.156 + else:
2.157 + end = _normalise_index(end, length)
2.158 +
2.159 + result = []
2.160 + while start < end:
2.161 + result.append(seq.__get_single_item__(start))
2.162 + start += 1
2.163 + return result
2.164 +
2.165 +# Special implementation functions.
2.166 +
2.167 +def _isinstance(obj, cls): pass
2.168 +
2.169 # Reference some names to ensure their existence. This should be everything
2.170 # mentioned in a get_builtin or load_builtin call. Instances from this module
2.171 # should be predefined constants.
3.1 --- a/rsvplib.py Mon Sep 27 23:30:55 2010 +0200
3.2 +++ b/rsvplib.py Mon Nov 01 01:22:44 2010 +0100
3.3 @@ -60,6 +60,14 @@
3.4 self.frame_stack = self.machine.frame_stack
3.5 self.local_sp_stack = self.machine.local_sp_stack
3.6
3.7 + def _get_absolute_index(self, pos, nelements):
3.8 + if pos >= 0 and pos < nelements:
3.9 + return pos
3.10 + elif pos < 0 and pos >= -nelements:
3.11 + return nelements + pos
3.12 + else:
3.13 + return None
3.14 +
3.15 def builtins_int_arithmetic_op(self, op):
3.16 frame = self.local_sp_stack[-1]
3.17
3.18 @@ -270,7 +278,7 @@
3.19 addr = list_value.ref + 1
3.20 self.machine.save(addr, DataValue(None, new_fragment))
3.21
3.22 - def builtins_list_getitem(self):
3.23 + def builtins_list_get_single_item(self):
3.24 frame = self.local_sp_stack[-1]
3.25
3.26 # Get the operand address.
3.27 @@ -291,24 +299,14 @@
3.28 header = self.machine.load(fragment.ref)
3.29 nelements = header.occupied_size - 1
3.30
3.31 - # Test operand suitability.
3.32 -
3.33 - if self.machine._CheckInstance(item_value.ref, self.int_class):
3.34 + # NOTE: Assume single location for data and header.
3.35
3.36 - # NOTE: Assume single location for data and header.
3.37 -
3.38 - item_pos = self.machine.load(item_value.ref + 1)
3.39 + item_pos = self.machine.load(item_value.ref + 1)
3.40
3.41 - if item_pos >= 0 and item_pos < nelements:
3.42 - pass
3.43 - elif item_pos < 0 and item_pos >= -nelements:
3.44 - item_pos = nelements + item_pos
3.45 - else:
3.46 - self.machine.exception = self.machine._MakeObject(2, self.index_error_instance)
3.47 - return self.machine.RaiseException()
3.48 + item_pos = self._get_absolute_index(item_pos, nelements)
3.49
3.50 - else:
3.51 - self.machine.exception = self.machine._MakeObject(2, self.type_error_instance)
3.52 + if item_pos is None:
3.53 + self.machine.exception = self.machine._MakeObject(2, self.index_error_instance)
3.54 return self.machine.RaiseException()
3.55
3.56 # NOTE: Assume single location for header.
3.57 @@ -417,7 +415,7 @@
3.58
3.59 self.machine.result = DataValue(addr, addr)
3.60
3.61 - def builtins_tuple_getitem(self):
3.62 + def builtins_tuple_get_single_item(self):
3.63 frame = self.local_sp_stack[-1]
3.64
3.65 # Get the operand address.
3.66 @@ -438,11 +436,9 @@
3.67
3.68 item_pos = self.machine.load(item_value.ref + 1)
3.69
3.70 - if item_pos >= 0 and item_pos < nelements:
3.71 - pass
3.72 - elif item_pos < 0 and item_pos >= -nelements:
3.73 - item_pos = nelements + item_pos
3.74 - else:
3.75 + item_pos = self._get_absolute_index(item_pos, nelements)
3.76 +
3.77 + if item_pos is None:
3.78 self.machine.exception = self.machine._MakeObject(2, self.index_error_instance)
3.79 return self.machine.RaiseException()
3.80
3.81 @@ -488,11 +484,11 @@
3.82 "__builtins__.int.__or__" : builtins_int_or,
3.83 "__builtins__.int.__ror__" : builtins_int_or,
3.84 "__builtins__.bool.__bool__" : builtins_bool_bool,
3.85 - "__builtins__.list.__getitem__" : builtins_list_getitem,
3.86 + "__builtins__.list.__get_single_item__" : builtins_list_get_single_item,
3.87 "__builtins__.list.__len__" : builtins_list_len,
3.88 "__builtins__.list.append" : builtins_list_append,
3.89 "__builtins__.tuple.__len__" : builtins_tuple_len,
3.90 - "__builtins__.tuple.__getitem__" : builtins_tuple_getitem,
3.91 + "__builtins__.tuple.__get_single_item__" : builtins_tuple_get_single_item,
3.92 "__builtins__.basestring.__lt__" : builtins_str_lt,
3.93 "__builtins__.basestring.__le__" : builtins_str_le,
3.94 "__builtins__.basestring.__gt__" : builtins_str_gt,