-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathlistobject.py
More file actions
195 lines (169 loc) · 5.51 KB
/
Copy pathlistobject.py
File metadata and controls
195 lines (169 loc) · 5.51 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
from builtin import signature
from interface import Object, null
from rpython.rlib.listsort import make_timsort_class
from rpython.rlib.rarithmetic import intmask
from numbers import Integer
import space
class List(Object):
_immutable_fields_ = ['contents']
__slots__ = ['contents']
def __init__(self, contents):
self.contents = contents
def __getitem__(self, index):
return self.contents[index]
def __len__(self):
return len(self.contents)
def hash(self):
mult = 1000003
x = 0x345678
z = len(self.contents)
for item in self.contents:
y = item.hash()
x = (x ^ y) * mult
z -= 1
mult += 82520 + z + z
x += 97531
return intmask(x)
def eq(self, other):
if not isinstance(other, List):
return False
if len(self) != len(other):
return False
for i in range(len(self)):
if not self[i].eq(other[i]):
return False
return True
def getattr(self, name):
if name == u'length':
return Integer(len(self.contents))
return Object.getattr(self, name)
def contains(self, item):
for obj in self.contents:
if obj.eq(item):
return True
return False
def getitem(self, index):
if isinstance(index, space.Slice):
start, stop, step = index.clamped(0, len(self.contents)-1)
result = []
for i in range(start, stop, step):
result.append(self.contents[i])
return List(result)
index = space.cast(index, Integer, u"index not an integer")
if not 0 <= index.value < len(self.contents):
raise space.unwind(space.LKeyError(self, index))
return self.contents[index.value]
def setitem(self, index, value):
# TODO: Add slice support to this side.
index = space.cast(index, Integer, u"index not an integer")
if not 0 <= index.value < len(self.contents):
raise space.unwind(space.LKeyError(self, index))
self.contents[index.value] = value
return value
def iter(self):
return ListIterator(iter(self.contents))
def repr(self):
out = []
for item in self.contents:
out.append(item.repr())
return u'[' + u', '.join(out) + u']'
@List.method(u"append", signature(List, Object))
def List_append(self, other):
self.contents.append(other)
return null
@List.method(u"extend", signature(List, Object))
def List_extend(self, iterable):
it = iterable.iter()
try:
while True:
self.contents.append(it.callattr(u"next", []))
except StopIteration as stop:
return space.null
return space.null
@List.method(u"insert", signature(List, Integer, Object))
def List_insert(self, index, obj):
val = index.value
if not 0 <= val <= len(self.contents):
raise space.unwind(space.LKeyError(self, index))
self.contents.insert(val, obj)
return space.null
@List.method(u"remove", signature(List, Object))
def List_remove(self, obj):
for index, item in enumerate(self.contents):
if item.eq(obj):
self.contents.pop(index)
return space.null
raise space.unwind(space.LValueError(self, obj))
@List.method(u"pop", signature(List, Integer, optional=1))
def List_pop(self, index):
if index:
index = index.value
else:
index = len(self.contents) - 1
if not 0 <= index < len(self.contents):
raise space.unwind(space.LKeyError(self, space.Integer(index)))
return self.contents.pop(index)
@List.method(u"index", signature(List, Object))
def List_index(self, obj):
for index, item in enumerate(self.contents):
if item.eq(obj):
return Integer(index)
raise space.unwind(space.LValueError(self, obj))
@List.method(u"count", signature(List, Object))
def List_count(self, obj):
count = 0
for item in self.contents:
if item.eq(obj):
count += 1
return Integer(count)
@List.method(u"sort", signature(List, Object, optional=1))
def List_sort(self, lt):
if not lt:
lt = space.operators.lt
sorter = ListSort(self.contents, len(self.contents))
sorter.w_lt = lt
self.contents = []
sorter.sort()
self.contents = sorter.list
return space.null
# def sorter_sorting(a, b):
# x = sorter.call([a, b])
# if isinstance(x, space.Integer):
# return x.value
# else:
# raise space.unwind(space.LTypeError(u"expected .sort cmp to return integers"))
## else:
## def ordinary_sorting(a, b):
##
# self.contents.sort(sorter_sorting)
# return space.null
@List.method(u"reverse", signature(List))
def List_reverse(self):
self.contents.reverse()
return space.null
class ListIterator(Object):
_immutable_fields_ = ['iterator']
def __init__(self, iterator):
self.iterator = iterator
def iter(self):
return self
@ListIterator.builtin_method
@signature(ListIterator)
def next(self):
return self.iterator.next()
@List.instantiator
def instantiate(argv):
list_ = List([])
if len(argv) > 0:
other = argv[0]
it = other.iter()
try:
while True:
list_.contents.append(it.callattr(u"next", []))
except StopIteration as stop:
pass
return list_
TimSort = make_timsort_class()
class ListSort(TimSort):
def lt(self, a, b):
return space.is_true(self.w_lt.call([a, b]))