\ -*- mode: forth -*-
\ $Id: lists.bigforth,v 1.1 2001/06/19 16:20:46 doug Exp $
\ http://www.bagley.org/~doug/shootout/
\ from Anton Ertl
0. argc @ 1- arg >number 2drop drop constant NUM
10000 constant SIZE
struct
cell% field list-next
cell% field list-val
end-struct list%
: make-list
0 0 SIZE -do
list% %alloc
i over list-val !
tuck list-next !
1 -loop
;
: copy-list
0 { w^ list2 }
list2 begin
over
while
list% %alloc dup >r swap !
dup list-val @ r@ list-val !
list-next @ r> list-next
repeat
off drop list2 @ ;
: move-head-to-tail
\ somehow this is an expensive noop
0 { w^ list2 }
list2 begin
over
while
\ move one element
over list-next dup @ 2>r
over list-next off
! r> r>
repeat
off drop list2 @ ;
: nreverse
\ destructive reverse
0 swap begin
dup
while
dup list-next @ >r
tuck list-next ! r>
repeat
drop ;
: move-tail-to-tail
\ use head-to-tail instead of head-to-head nreverse
nreverse move-head-to-tail ;
: list-equals
begin
dup
while
over
while
over list-val @ over list-val @ <> if
2drop false exit
endif
list-next @ swap list-next @
repeat then
= ;
: list-length
0 begin
over
while
1+ swap list-next @ swap
repeat
nip ;
s" wrong result" exception constant wrong-result
: main
0 NUM 0 ?do
drop
make-list dup copy-list
move-head-to-tail move-tail-to-tail swap nreverse
dup list-val @ SIZE <> wrong-result and throw
tuck list-equals 0= wrong-result and throw
list-length
loop ;
main 0 .r cr bye