Lichen

Annotated lib/__builtins__/list.py

849:81587921b9b4
2018-07-11 Paul Boddie Use the __store_via_object operations to set attributes.
paul@6 1
#!/usr/bin/env python
paul@6 2
paul@6 3
"""
paul@6 4
List objects.
paul@6 5
paul@516 6
Copyright (C) 2015, 2016, 2017 Paul Boddie <paul@boddie.org.uk>
paul@6 7
paul@6 8
This program is free software; you can redistribute it and/or modify it under
paul@6 9
the terms of the GNU General Public License as published by the Free Software
paul@6 10
Foundation; either version 3 of the License, or (at your option) any later
paul@6 11
version.
paul@6 12
paul@6 13
This program is distributed in the hope that it will be useful, but WITHOUT
paul@6 14
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
paul@6 15
FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
paul@6 16
details.
paul@6 17
paul@6 18
You should have received a copy of the GNU General Public License along with
paul@6 19
this program.  If not, see <http://www.gnu.org/licenses/>.
paul@6 20
"""
paul@6 21
paul@528 22
from __builtins__.iteration.iterator import itemiterator
paul@548 23
from __builtins__.sequence import sequence, _get_absolute_index
paul@356 24
from native import list_append, list_concat, list_element, list_init, \
paul@516 25
                   list_len, list_nonempty, list_setelement, list_setsize
paul@6 26
paul@224 27
class list(sequence):
paul@6 28
paul@6 29
    "Implementation of list."
paul@6 30
paul@6 31
    def __init__(self, args=None):
paul@6 32
paul@6 33
        "Initialise the list."
paul@6 34
paul@206 35
        # Reserve an attribute for a fragment reference along with some space
paul@206 36
        # for elements.
paul@159 37
paul@356 38
        self.__data__ = list_init(args is not None and len(args) or 0)
paul@159 39
paul@6 40
        if args is not None:
paul@6 41
            self.extend(args)
paul@6 42
paul@548 43
    def __delitem__(self, index):
paul@548 44
paul@548 45
        "Delete the item at 'index'."
paul@548 46
paul@548 47
        length = self.__len__()
paul@548 48
        index = _get_absolute_index(index, length)
paul@548 49
        last = length - 1
paul@548 50
paul@548 51
        while index < last:
paul@548 52
            self[index] = self[index + 1]
paul@548 53
            index += 1
paul@548 54
paul@548 55
        # NOTE: Should truncate the allocated list after several pops.
paul@548 56
paul@548 57
        list_setsize(self.__data__, last)
paul@548 58
paul@6 59
    def __setslice__(self, start, end, slice): pass
paul@6 60
    def __delslice__(self, start, end): pass
paul@206 61
paul@206 62
    def append(self, value):
paul@206 63
paul@206 64
        "Append 'value' to the list."
paul@206 65
paul@356 66
        list_append(self, value)
paul@206 67
paul@804 68
    def insert(self, index, value):
paul@804 69
paul@804 70
        "Insert at 'index' the given 'value'."
paul@804 71
paul@804 72
        length = self.__len__()
paul@804 73
        index = _get_absolute_index(index, length)
paul@804 74
paul@804 75
        if index == length:
paul@804 76
            self.append(value)
paul@804 77
            return
paul@804 78
        elif index > length:
paul@804 79
            raise IndexError, index
paul@804 80
paul@804 81
        i = length - 1
paul@804 82
        self.append(self.__getitem__(i))
paul@804 83
paul@804 84
        while i > index:
paul@804 85
            self.__setitem__(i, self.__getitem__(i - 1))
paul@804 86
            i -= 1
paul@804 87
paul@804 88
        self.__setitem__(index, value)
paul@6 89
paul@6 90
    def extend(self, iterable):
paul@6 91
paul@6 92
        "Extend the list with the contents of 'iterable'."
paul@6 93
paul@6 94
        for i in iterable:
paul@6 95
            self.append(i)
paul@6 96
paul@516 97
    def pop(self):
paul@516 98
paul@516 99
        "Remove the last item from the list, returning the item."
paul@516 100
paul@516 101
        i = self[-1]
paul@516 102
paul@516 103
        # NOTE: Should truncate the allocated list after several pops.
paul@516 104
paul@516 105
        list_setsize(self.__data__, self.__len__() - 1)
paul@516 106
        return i
paul@516 107
paul@804 108
    def reverse(self):
paul@804 109
paul@804 110
        "Reverse the list in-place."
paul@804 111
paul@804 112
        length = self.__len__()
paul@804 113
        i = 0
paul@804 114
        j = length - 1
paul@804 115
paul@804 116
        while i < j:
paul@804 117
            item = self.__getitem__(j)
paul@804 118
            self.__setitem__(j, self.__getitem__(i))
paul@804 119
            self.__setitem__(i, item)
paul@804 120
            i += 1
paul@804 121
            j -= 1
paul@516 122
paul@6 123
    def sort(self, cmp=None, key=None, reverse=0): pass
paul@140 124
paul@140 125
    def __len__(self):
paul@140 126
paul@140 127
        "Return the length of the list."
paul@140 128
paul@356 129
        return list_len(self.__data__)
paul@140 130
paul@516 131
    def __add__(self, other):
paul@516 132
paul@516 133
        "Add this list to 'other', producing a new list."
paul@516 134
paul@516 135
        l = list(self)
paul@516 136
        l.extend(other)
paul@516 137
        return l
paul@206 138
paul@206 139
    def __iadd__(self, other):
paul@206 140
paul@206 141
        "Concatenate 'other' to the list."
paul@206 142
paul@206 143
        if isinstance(other, list):
paul@356 144
            list_concat(self, other.__data__)
paul@206 145
        else:
paul@206 146
            self.extend(other)
paul@206 147
        return self
paul@198 148
paul@799 149
    def __mul__(self, other):
paul@799 150
paul@799 151
        "Replicate this sequence 'other' times."
paul@799 152
paul@799 153
        return self._mul(list(self), other)
paul@799 154
paul@799 155
    def __imul__(self, other):
paul@799 156
paul@799 157
        "Replicate this list 'other' times."
paul@799 158
paul@799 159
        return self._mul(self, other)
paul@799 160
paul@799 161
    def _mul(self, l, other):
paul@799 162
paul@799 163
        "Replicate 'l' 'other' times."
paul@799 164
paul@802 165
        copy = list(self)
paul@799 166
        while other > 1:
paul@802 167
            l.extend(copy)
paul@799 168
            other -= 1
paul@799 169
        return l
paul@799 170
paul@198 171
    def __str__(self):
paul@198 172
paul@227 173
        "Return a string representation."
paul@198 174
paul@227 175
        return self._str("[", "]")
paul@6 176
paul@222 177
    __repr__ = __str__
paul@222 178
paul@6 179
    def __bool__(self):
paul@6 180
paul@6 181
        "Lists are true if non-empty."
paul@6 182
paul@356 183
        return list_nonempty(self.__data__)
paul@6 184
paul@6 185
    def __iter__(self):
paul@6 186
paul@6 187
        "Return an iterator."
paul@6 188
paul@290 189
        return itemiterator(self)
paul@6 190
paul@6 191
    # Special implementation methods.
paul@6 192
paul@140 193
    def __get_single_item__(self, index):
paul@140 194
paul@194 195
        "Return the item at the normalised (positive) 'index'."
paul@194 196
paul@265 197
        self._check_index(index)
paul@356 198
        return list_element(self.__data__, index)
paul@6 199
paul@227 200
    def __set_single_item__(self, index, value):
paul@227 201
paul@227 202
        "Set at the normalised (positive) 'index' the given 'value'."
paul@227 203
paul@265 204
        self._check_index(index)
paul@356 205
        return list_setelement(self.__data__, index, value)
paul@227 206
paul@6 207
# vim: tabstop=4 expandtab shiftwidth=4