A start on VList.
This commit is contained in:
parent
10edbd0ee0
commit
8a3f3aff5c
|
|
@ -0,0 +1,96 @@
|
|||
'''
|
||||
An exploration of Phil Bagwell's VList.
|
||||
|
||||
A VList is modeled as a 5-tuple:
|
||||
base: VList
|
||||
offset: int (indexing base VList data)
|
||||
size: int
|
||||
last_used: to make a mutable int it's an int in a list
|
||||
It's a count here rather than an offset!
|
||||
data: a list of length length
|
||||
|
||||
a Pointer to a VList is a pair of (VList and offset).
|
||||
|
||||
'''
|
||||
|
||||
def new_VList(base=(), offset=0, size=1):
|
||||
assert size >= 1
|
||||
return (base, offset, size, [0], [None] * length)
|
||||
|
||||
|
||||
# In Fig 2 a list has been created with the integers (8,7,6,5,4,3)
|
||||
|
||||
o1 = ((), 0, 1, [1], [3])
|
||||
o2 = (o1, 0, 2, [2], [4, 5])
|
||||
o3 = (o2, 1, 4, [3], [6, 7, 8, None])
|
||||
|
||||
p0 = (o3, 2) # points to 8
|
||||
p1 = (o3, 0) # points to 6
|
||||
|
||||
# cons(9, p1) = o4
|
||||
|
||||
o4 = (o3, 0, 1, [1], [9])
|
||||
p2 = (o4, 0) # points to 9
|
||||
|
||||
|
||||
|
||||
def cons(thing, vlist_ptr):
|
||||
(base, offset, size, last_used_list, data), pointer_offset = vlist_ptr
|
||||
[last_used] = last_used_list
|
||||
|
||||
'''
|
||||
|
||||
During the consing of (9) the pointer offset
|
||||
is compared with the last used offset, LastUsed. If it is the same and less than
|
||||
the block size then it is simply incremented, the new entry made and LastUsed
|
||||
updated.
|
||||
|
||||
'''
|
||||
if pointer_offset == last_used - 1 and last_used < size:
|
||||
pointer_offset += 1
|
||||
data[pointer_offset] = thing
|
||||
last_used_list[0] = last_used + 1
|
||||
return vlist_ptr[0], pointer_offset
|
||||
'''
|
||||
|
||||
If on the other-hand the pointer offset is less than the LastUsed a cons is being applied
|
||||
to the tail of a longer list, as is the case with the (9). In this case a new list block
|
||||
must be allocated and its Base-Offset pointer set to the tail contained in the original
|
||||
list. The offset part being set to the point in tail that must be extended. The new
|
||||
entry can now be made and additional elements added.
|
||||
|
||||
'''
|
||||
|
||||
# Is this where we increase the size x 2?
|
||||
# size <<= 1 ; l = [None] * size ; l[0] = thing
|
||||
# return (vlist_ptr[0], pointer_offset, size, [1], l), 0
|
||||
|
||||
return (vlist_ptr[0], pointer_offset, 1, [1], [thing]), 0
|
||||
|
||||
|
||||
p3 = cons(10, p0)
|
||||
|
||||
|
||||
def head(vlist_ptr):
|
||||
vlist, offset = vlist_ptr
|
||||
if not vlist:
|
||||
raise ValueError("empty list has no head!")
|
||||
return vlist[-1][offset]
|
||||
|
||||
|
||||
def tail(vlist_ptr):
|
||||
vlist, offset = vlist_ptr
|
||||
offset -= 1
|
||||
return vlist[:2] if offset < 0 else (vlist, offset)
|
||||
|
||||
|
||||
def iter_vlist(vlist_ptr):
|
||||
while vlist_ptr[0]:
|
||||
yield head(vlist_ptr)
|
||||
vlist_ptr = tail(vlist_ptr)
|
||||
|
||||
|
||||
for i, p in enumerate((p0, p1, p2, p3)):
|
||||
print(f'p{i}')
|
||||
print(' '.join(map(str, iter_vlist(p))))
|
||||
print()
|
||||
Loading…
Reference in New Issue