I was going to post this as an example, but it keeps crashing. I traced it to the fact that the constructor and destructor are not called. If I use a pointer and new/delete, the destructor is called, but not the constructor.
This code is a conversion of a C++ template class: LinkedList<V>.
autodefine "off"
type p_listnode
pointer _data
pointer _next
pointer prev
end type
class LinkedList
private
pointer head
pointer tail
public
declare LinkedList( )
declare _LinkedList( )
declare add( pointer d ), pointer
declare addHead( pointer d ), pointer
declare insertAfter( pointer node, pointer d ), pointer
declare insertBefore( pointer node, pointer d ), pointer
declare remove( pointer node ), pointer
declare removeAll( )
declare getFirst( ), pointer
declare getLast( ), pointer
declare getNext( pointer node ), pointer
declare getPrev( pointer node ), pointer
declare nodeData( pointer node ), pointer
declare enumerate( uint cb )
declare enumerateBackwards( uint cb )
end class
declare __listcb( pointer d )
sub llfree( pointer _data )
delete _data
end sub
sub LinkedList::LinkedList( )
head = new( p_listnode, 1 )
tail = new( p_listnode, 1 )
*<p_listnode>head._next = tail
*<p_listnode>head._data = 0
*<p_listnode>head.prev = 0
*<p_listnode>tail._next = 0
*<p_listnode>tail._data = 0
*<p_listnode>tail.prev = head
end sub
sub LinkedList::_LinkedList( )
removeAll( )
delete head
delete tail
end sub
sub LinkedList::add( pointer d )
return insertBefore( tail, d )
end sub
sub LinkedList::addHead( pointer d )
return insertAfter( head, d )
end sub
sub LinkedList::insertAfter( pointer node, pointer d )
pointer newnode : newnode = new( p_listnode, 1 )
*<p_listnode>newnode.prev = node
*<p_listnode>newnode._next = *<p_listnode>node._next
if *<p_listnode>node._next then *<p_listnode>node.*<p_listnode>_next.prev = newnode
*<p_listnode>node._next = newnode
*<p_listnode>node._data = d
return d
end sub
sub LinkedList::insertBefore( pointer node, pointer d )
pointer newnode : newnode = new( p_listnode, 1 )
*<p_listnode>newnode._next = node
*<p_listnode>newnode.prev = *<p_listnode>node.prev
if *<p_listnode>node.prev <> 0 then *<p_listnode>node.*<p_listnode>prev._next = newnode
*<p_listnode>node.prev = newnode
*<p_listnode>node._data = d
return d
end sub
sub LinkedList::remove( pointer node )
'' Can't remove head or tail
if *<p_listnode>node._next = 0 or *<p_listnode>node.prev = 0 then return 0
pointer d : d = *<p_listnode>node._data
delete node
*<p_listnode>node.*<p_listnode>_next.prev = *<p_listnode>node.prev
*<p_listnode>node.*<p_listnode>prev._next = *<p_listnode>node._next
return d
end sub
sub LinkedList::removeAll( )
pointer node : node = *<p_listnode>head._next
pointer temp
while node <> tail
temp = *<p_listnode>node._next
delete node
node = temp
wend
end sub
sub LinkedList::getFirst( )
return *<p_listnode>head._next
end sub
sub LinkedList::getLast( )
return *<p_listnode>tail.prev
end sub
sub LinkedList::getNext( pointer node )
pointer nxt : nxt = *<p_listnode>node._next
if nxt <> tail then return nxt
return 0
end sub
sub LinkedList::getPrev( pointer node )
pointer prv : prv = *<p_listnode>node.prev
if prv <> head then return prv
return 0
end sub
sub LinkedList::nodeData( pointer node )
return *<p_listnode>node._data
end sub
sub LinkedList::enumerate( uint cb )
pointer node
node = getFirst( )
while node <> 0
!<__listcb>cb( *<p_listnode>node._data )
node = getNext( node )
wend
end sub
sub LinkedList::enumerateBackwards( uint cb )
pointer node
node = getLast( )
while node <> 0
!<__listcb>cb( *<p_listnode>node._data )
node = getPrev( node )
wend
end sub
''-----
'' Enumeration subroutine
sub listEnumSub( pointer d )
print *<string>d, " ",
end sub
''-----
'' Test program
LinkedList theList
theList.add( "my" )
theList.add( "name" )
theList.add( "is" )
theList.add( "Parker" )
theList.addHead( "Hello," )
theList.enumerate( &listEnumSub )
LinkedList is already a type, defined in ebstd.incc. It is part of the built in Emergence linked list functions.
So just rename your class to something else and it works fine. And I will add an error message ;)
And you had an error in your coding as well. In the insertbefore and insertafter methods. Here are the corrected ones, I renamed the class to PointerList since that is what it is ;)
sub PointerList::insertAfter( pointer node, pointer d )
pointer newnode : newnode = new( p_listnode, 1 )
*<p_listnode>newnode.prev = node
*<p_listnode>newnode._next = *<p_listnode>node._next
if *<p_listnode>node._next then *<p_listnode>node.*<p_listnode>_next.prev = newnode
*<p_listnode>node._next = newnode
*<p_listnode>newnode._data = d
return d
end sub
sub PointerList::insertBefore( pointer node, pointer d )
pointer newnode : newnode = new( p_listnode, 1 )
*<p_listnode>newnode._next = node
*<p_listnode>newnode.prev = *<p_listnode>node.prev
if *<p_listnode>node.prev <> 0 then *<p_listnode>node.*<p_listnode>prev._next = newnode
*<p_listnode>node.prev = newnode
*<p_listnode>newnode._data = d
return d
end sub
Okay, I've renamed it "PLinkedList" and it works fine. I also changed two bugs in insertBefore() and insertAfter() where I was changing the data member of the wrong node, so the data would always turn out as null (this error didn't exist in the C++ version, it was an error in translation).
Since this was a template class, it doesn't have an option to delete data members when it removes them. Instead I provided a short subrouine
// callback to free pointer lists
template<class V>
void llfree( V data )
{
delete data;
}
This subroutine also exists in the emergence version. To delete all the data members when you remove them, use this code:
list.enumerate( &llfree )
list.removeAll( )
To delete just one member when you remove it, use this:
pointer d
...
d = list.remove( node )
delete d
This is my working version of it.
autodefine "off"
type p_listnode
pointer _data
pointer _next
pointer prev
end type
class PLinkedList
private
pointer head
pointer tail
public
declare PLinkedList( )
declare _PLinkedList( )
declare add( pointer d ), pointer
declare addHead( pointer d ), pointer
declare insertAfter( pointer node, pointer d ), pointer
declare insertBefore( pointer node, pointer d ), pointer
declare remove( pointer node ), pointer
declare removeAll( )
declare getFirst( ), pointer
declare getLast( ), pointer
declare getNext( pointer node ), pointer
declare getPrev( pointer node ), pointer
declare nodeData( pointer node ), pointer
declare enumerate( uint cb )
declare enumerateBackwards( uint cb )
end class
declare __listcb( pointer d )
sub llfree( pointer _data )
delete _data
end sub
sub PLinkedList::PLinkedList( )
head = new( p_listnode, 1 )
tail = new( p_listnode, 1 )
*<p_listnode>head._next = tail
*<p_listnode>head._data = 0
*<p_listnode>head.prev = 0
*<p_listnode>tail._next = 0
*<p_listnode>tail._data = 0
*<p_listnode>tail.prev = head
end sub
sub PLinkedList::_PLinkedList( )
removeAll( )
delete head
delete tail
end sub
sub PLinkedList::add( pointer d )
return insertBefore( tail, d )
end sub
sub PLinkedList::addHead( pointer d )
return insertAfter( head, d )
end sub
sub PLinkedList::insertAfter( pointer node, pointer d )
pointer newnode : newnode = new( p_listnode, 1 )
*<p_listnode>newnode.prev = node
*<p_listnode>newnode._next = *<p_listnode>node._next
if *<p_listnode>node._next then *<p_listnode>node.*<p_listnode>_next.prev = newnode
*<p_listnode>node._next = newnode
*<p_listnode>newnode._data = d
return d
end sub
sub PLinkedList::insertBefore( pointer node, pointer d )
pointer newnode : newnode = new( p_listnode, 1 )
*<p_listnode>newnode._next = node
*<p_listnode>newnode.prev = *<p_listnode>node.prev
if *<p_listnode>node.prev <> 0 then *<p_listnode>node.*<p_listnode>prev._next = newnode
*<p_listnode>node.prev = newnode
*<p_listnode>newnode._data = d
return d
end sub
sub PLinkedList::remove( pointer node )
'' Can't remove head or tail
if *<p_listnode>node._next = 0 or *<p_listnode>node.prev = 0 then return 0
pointer d : d = *<p_listnode>node._data
delete node
*<p_listnode>node.*<p_listnode>_next.prev = *<p_listnode>node.prev
*<p_listnode>node.*<p_listnode>prev._next = *<p_listnode>node._next
return d
end sub
sub PLinkedList::removeAll( )
pointer node : node = *<p_listnode>head._next
pointer temp
while node <> tail
temp = *<p_listnode>node._next
delete node
node = temp
wend
end sub
sub PLinkedList::getFirst( )
return *<p_listnode>head._next
end sub
sub PLinkedList::getLast( )
return *<p_listnode>tail.prev
end sub
sub PLinkedList::getNext( pointer node )
pointer nxt : nxt = *<p_listnode>node._next
if nxt <> tail then return nxt
return 0
end sub
sub PLinkedList::getPrev( pointer node )
pointer prv : prv = *<p_listnode>node.prev
if prv <> head then return prv
return 0
end sub
sub PLinkedList::nodeData( pointer node )
return *<p_listnode>node._data
end sub
sub PLinkedList::enumerate( uint cb )
pointer node
node = getFirst( )
while node <> 0
!<__listcb>cb( *<p_listnode>node._data )
node = getNext( node )
wend
end sub
sub PLinkedList::enumerateBackwards( uint cb )
pointer node
node = getLast( )
while node <> 0
!<__listcb>cb( *<p_listnode>node._data )
node = getPrev( node )
wend
end sub
''-----
'' Enumeration subroutine
sub listEnumSub( pointer d )
print *<string>d, " ",
end sub
''-----
'' Test program
PLinkedList theList
theList.add( "my" )
theList.add( "name" )
theList.add( "is" )
theList.add( "Parker" )
theList.addHead( "Hello," )
theList.enumerate( &listEnumSub )
do:until inkey$<>""
Edit - I found that out a few minutes ago too. It was a translation error - going through code quickly I didn't see the difference between node and newnode.