Attaching files doesn't seem to work, so here is a copy of those modules:
cBasicList.e
/* CSH/cBasicList.e 12-11-2016 by Chris Handley
A list implementation which is 'as simple as possible', while still supporting sub-classing, as well as removal/insertion of multiple nodes in one go.
Lists are circular, and always contain a special 'empty' node after any normal nodes.
This 'empty' node is known as the "pastEnd" node, since it is past the end of the list.
NEVER remove this node from the list (but it can be used to mark the end of a range of nodes that should be removed).
Optimisations are certainly possible, but at the expense of less readable code and/or a more complex interface.
At which point it would no-longer be 'as simple as possible'! (And it's unlikely your program will be noticably faster...)
Still, this module should be a good starting point for your own list classes.
*/
/* Public methods of *cBasicList*:
new()
infoStart() RETURNS start:PTR TO cBasicNode
infoPastEnd() RETURNS pastEnd:PTR TO cBasicNode
create() RETURNS node:PTR TO cBasicNode
destroy(first:PTR TO cBasicNode, pastLast=NIL:PTR TO cBasicNode)
->helper methods:
isEmpty() RETURNS isEmpty:BOOL
append(nodes:PTR TO cBasicNode)
prepend(nodes:PTR TO cBasicNode)
*/
/* Public methods of *cBasicNode*:
infoNext() RETURNS next:PTR TO cBasicNode
infoPrev() RETURNS prev:PTR TO cBasicNode
beforeInsert(nodes:PTR TO cBasicNode)
afterInsert(nodes:PTR TO cBasicNode)
remove(pastLast=NIL:PTR TO cBasicNode) RETURNS nodes:PTR TO cBasicNode
->helper methods:
read() RETURNS data
*/
/*****************************/
CLASS cBasicList
->circular list
pastEnd:PTR TO cBasicNode ->empty node after last 'real' node in list
ENDCLASS
PROC new() OF cBasicList
self.pastEnd := self.create()
ENDPROC
PROC end() OF cBasicList
IF self.pastEnd THEN END self.pastEnd.next
SUPER self.end()
ENDPROC
PROC infoStart() OF cBasicList IS self.pastEnd.next
PROC infoPastEnd() OF cBasicList IS self.pastEnd
PROC create() OF cBasicList RETURNS node:PTR TO cBasicNode
DEF newNode:OWNS PTR TO cBasicNode
newNode := self.makeNode() ; newNode.new()
node := newNode
node.prev := node
node.next := PASS newNode
ENDPROC
PROC destroy(first:PTR TO cBasicNode, pastLast=NIL:PTR TO cBasicNode) OF cBasicList
DEF nodes:PTR TO cBasicNode
IF nodes := first.remove(pastLast) THEN END nodes.next
ENDPROC
->helper methods
PROC isEmpty() OF cBasicList RETURNS isEmpty:BOOL IS self.pastEnd.next = self.pastEnd
PROC append(nodes:PTR TO cBasicNode) OF cBasicList IS self.pastEnd.beforeInsert(nodes)
PROC prepend(nodes:PTR TO cBasicNode) OF cBasicList IS self.pastEnd.afterInsert(nodes)
->PROTECTED
PROC makeNode() OF cBasicList RETURNS node:OWNS PTR TO cBasicNode
NEW node
ENDPROC
/*****************************/
CLASS cBasicNode
next:OWNS PTR TO cBasicNode
prev: PTR TO cBasicNode
ENDCLASS
->PROTECTED
PROC new() OF cBasicNode IS EMPTY
PROC end() OF cBasicNode
DEF node:OWNS PTR TO cBasicNode, next:OWNS PTR TO cBasicNode
->destroy later nodes, without using the stack
self.prev.next := NIL
next := PASS self.next
WHILE next
node := PASS next
next := PASS node.next
END node
ENDWHILE
SUPER self.end()
ENDPROC
PROC infoNext() OF cBasicNode IS self.next
PROC infoPrev() OF cBasicNode IS self.prev
->insert the supplied node(s) before us
PROC beforeInsert(nodes:PTR TO cBasicNode) OF cBasicNode
DEF firstNodes:OWNS PTR TO cBasicNode, lastNodes:PTR TO cBasicNode, beforeInsert:PTR TO cBasicNode, afterInsert:OWNS PTR TO cBasicNode
IF nodes = NIL THEN RETURN
lastNodes := nodes.prev
firstNodes := PASS lastNodes.next ->nodes
beforeInsert := self.prev
afterInsert := PASS beforeInsert.next ->self
firstNodes.prev := beforeInsert
afterInsert.prev := lastNodes
beforeInsert.next := PASS firstNodes
lastNodes.next := PASS afterInsert
ENDPROC
->insert the supplied node(s) after us
->NOTE: Inserting after the pastEnd node will put the nodes at the START of the list!
PROC afterInsert(nodes:PTR TO cBasicNode) OF cBasicNode
DEF firstNodes:OWNS PTR TO cBasicNode, lastNodes:PTR TO cBasicNode, beforeInsert:PTR TO cBasicNode, afterInsert:OWNS PTR TO cBasicNode
IF nodes = NIL THEN RETURN
lastNodes := nodes.prev
firstNodes := PASS lastNodes.next ->nodes
beforeInsert := self
afterInsert := PASS self.next
firstNodes.prev := beforeInsert
afterInsert.prev := lastNodes
beforeInsert.next := PASS firstNodes
lastNodes.next := PASS afterInsert
ENDPROC
->remove the current node from the list, or a range of nodes if "pastLast" is supplied
->NOTE: It will return NIL for an empty range (i.e. when "pastLast" is the same as the current node).
PROC remove(pastLast=NIL:PTR TO cBasicNode) OF cBasicNode RETURNS nodes:PTR TO cBasicNode
DEF firstNodes:OWNS PTR TO cBasicNode, lastNodes:PTR TO cBasicNode, beforeRemove:PTR TO cBasicNode, afterRemove:OWNS PTR TO cBasicNode
IF self = pastLast THEN RETURN NIL
nodes := self
firstNodes := PASS self.prev.next ->self
lastNodes := IF pastLast THEN pastLast.prev ELSE self
beforeRemove := firstNodes.prev
afterRemove := PASS lastNodes.next
firstNodes.prev := lastNodes
afterRemove.prev := beforeRemove
beforeRemove.next := PASS afterRemove
lastNodes.next := PASS firstNodes
ENDPROC
->helper methods
PROC read() OF cBasicNode RETURNS data IS 0
/*****************************/
cBasicList_STRING.e
/* CSH/cBasicList_STRING.e 12-11-2016
A sub-class of cBasicList for STRINGs.
*/
/* Public methods of *cBasicList_STRING*:
new()
infoStart() RETURNS start:PTR TO cBasicNode_STRING
infoPastEnd() RETURNS pastEnd:PTR TO cBasicNode_STRING
create(string=NILS:OWNS STRING) RETURNS node:PTR TO cBasicNode_STRING
destroy(first:PTR TO cBasicNode, pastLast=NIL:PTR TO cBasicNode)
->helper methods:
isEmpty() RETURNS isEmpty:BOOL
append(nodes:PTR TO cBasicNode)
prepend(nodes:PTR TO cBasicNode)
*/
/* Public methods of *cBasicNode_STRING*:
infoNext() RETURNS next:PTR TO cBasicNode_STRING
infoPrev() RETURNS prev:PTR TO cBasicNode_STRING
beforeInsert(nodes:PTR TO cBasicNode)
afterInsert(nodes:PTR TO cBasicNode)
remove(pastLast=NIL:PTR TO cBasicNode) RETURNS nodes:PTR TO cBasicNode_STRING
->helper methods:
read() RETURNS data:STRING
*/
/* Public members of *cBasicNode_STRING*:
data:OWNS STRING
*/
PUBLIC MODULE '*cBasicList'
/*****************************/
CLASS cBasicList_STRING OF cBasicList
ENDCLASS
PROC new() OF cBasicList_STRING
SUPER self.new()
self.pastEnd::cBasicNode_STRING.data := NEW ''
ENDPROC
PROC infoStart() OF cBasicList_STRING IS SUPER self.infoStart()::cBasicNode_STRING
PROC infoPastEnd() OF cBasicList_STRING IS self.pastEnd::cBasicNode_STRING
PROC create(string=NILS:OWNS STRING) OF cBasicList_STRING RETURNS node:PTR TO cBasicNode_STRING
node := SUPER self.create()::cBasicNode_STRING
node.data := PASS string
ENDPROC
->PROTECTED
PROC makeNode() OF cBasicList_STRING RETURNS node:OWNS PTR TO cBasicNode_STRING
NEW node
ENDPROC
/*****************************/
CLASS cBasicNode_STRING OF cBasicNode PUBLIC
data:OWNS STRING
ENDCLASS
PROC end() OF cBasicNode_STRING
END self.data
SUPER self.end()
ENDPROC
PROC infoNext() OF cBasicNode_STRING IS self.next::cBasicNode_STRING
PROC infoPrev() OF cBasicNode_STRING IS self.prev::cBasicNode_STRING
PROC remove(pastLast=NIL:PTR TO cBasicNode) OF cBasicNode_STRING RETURNS nodes:PTR TO cBasicNode_STRING
nodes := SUPER self.remove(pastLast)::cBasicNode_STRING
ENDPROC
PROC read() OF cBasicNode_STRING IS self.data
cBasicList_STRING_test.e
MODULE '*cBasicList_STRING'
PROC main()
DEF list:OWNS PTR TO cBasicList_STRING, node:PTR TO cBasicNode_STRING, floating:PTR TO cBasicNode_STRING
->build a list
NEW list.new()
list.append(list.create(NEW 'Hello '))
list.append(list.create(NEW 'new '))
list.append(list.create(NEW 'world! '))
printList(list) ->Hello new world!
->do some tests
node := list.infoStart()
floating := node.remove()
list.infoPastEnd().beforeInsert(floating)
printList(list) ->new world! Hello
node := list.infoPastEnd().infoPrev()
floating := node.remove()
list.infoStart().beforeInsert(floating)
printList(list) ->Hello new world!
node := list.infoStart()
floating := node.remove()
list.infoPastEnd().afterInsert(floating)
printList(list) ->Hello new world!
node := list.infoStart().infoNext()
floating := node.remove()
list.infoStart().beforeInsert(floating)
printList(list) ->new Hello world!
node := list.infoStart()
floating := node.remove(list.infoPastEnd().infoPrev())
list.infoPastEnd().beforeInsert(floating)
printList(list) ->world! new Hello
Print('Finished.\n')
FINALLY
PrintException()
END list
ENDPROC
PROC printList(list:PTR TO cBasicList_STRING)
DEF pastEnd, node:PTR TO cBasicNode_STRING
pastEnd := list.infoPastEnd()
node := list.infoStart()
WHILE node <> pastEnd
Print(node.data) ->or Print(node.read())
node := node.infoNext()
ENDWHILE
Print('\n')
ENDPROC