duskos

dusk os fork
git clone git://git.alexwennerberg.com/duskos
Log | Files | Refs | README | LICENSE

commit a22123482065fd477dec82127773a4bfbbbf67d6
parent 8e1a457e3438c84ef6b547a47bce241e4694a270
Author: Virgil Dupras <hsoft@hardcoded.net>
Date:   Tue, 31 Jan 2023 17:02:04 -0500

lib/ll: new unit

extract a few words from bootlo, and add a few others.

Diffstat:
Mfs/comp/c/lib.fs | 1+
Mfs/comp/c/type.fs | 1+
Mfs/doc/dict.txt | 8++------
Afs/doc/lib/ll.txt | 20++++++++++++++++++++
Afs/lib/ll.fs | 16++++++++++++++++
Mfs/tests/kernel.fs | 12------------
Mfs/tests/lib/all.fs | 1+
Afs/tests/lib/ll.fs | 24++++++++++++++++++++++++
Mfs/text/ed.fs | 13++++++-------
Mfs/xcomp/bootlo.fs | 5-----
10 files changed, 71 insertions(+), 30 deletions(-)

diff --git a/fs/comp/c/lib.fs b/fs/comp/c/lib.fs @@ -3,6 +3,7 @@ ?f<< /comp/c/cc.fs ?f<< /lib/str.fs ?f<< /lib/fmt.fs +?f<< /lib/ll.fs \ A few system word proxies :c void abort(); diff --git a/fs/comp/c/type.fs b/fs/comp/c/type.fs @@ -2,6 +2,7 @@ ?f<< /lib/str.fs ?f<< /lib/arena.fs ?f<< /lib/meta.fs +?f<< /lib/ll.fs ?f<< /comp/c/tok.fs \ When we parse a type, we can almost never write it directly to "here" because diff --git a/fs/doc/dict.txt b/fs/doc/dict.txt @@ -254,15 +254,11 @@ n case .. of condition .. endof .. endcase llnext ll -- ll Yield next LL element. llend ll -- ll Iterate LL until we reach the last element. -llprev tgt ll -- ll From "ll", iterate LL until we reach the element when the - LL pointer points to "tgt". llappend elem ll -- Append "elem" at the end of "ll". lladd ll -- ll Write a new LL element to here, yield it, then write its address to the last element of "ll". -llinsert elem ll -- Insert "elem" between "ll" and its next element. If "ll" - is the last element of the list, this is equivalent to - "llappend". -llcnt ll -- n Yield the number of elements in "ll". + +For more, see lib/ll. ## Dictionary diff --git a/fs/doc/lib/ll.txt b/fs/doc/lib/ll.txt @@ -0,0 +1,20 @@ +# Linked lists + +A collection of helpers around linked lists. + +Values: + +llprev After a llfind or a llitern, llprev is the element preceding the result. + It is 0 when no iteration took place. +llidx After a llfind or a llitern, llidx is the number of iterations that took + place. + +Words: + +llinsert elem ll -- Insert "elem" between "ll" and its next element. If "ll" + is the last element of the list, this is equivalent to + "llappend". +llcnt ll -- n Yield the number of elements in "ll". +llfind elem ll -- f Check whether "elem" exists in "ll". +llitern n ll -- elem Iterate "n" time in "ll" and return the resulting element + or 0 if end of list was reached. diff --git a/fs/lib/ll.fs b/fs/lib/ll.fs @@ -0,0 +1,16 @@ +0 value llprev +0 value llidx + +: llinsert ( elem ll -- ) over swap @! swap ! ; +: llcnt ( ll -- count ) 0 >r begin ?dup not if r> neg exit then llnext next ; +: llitern ( n ll -- elem ) + over to llidx 0 to llprev over if swap >r begin ( line ) + dup to llprev llnext + dup not if r@ 1- neg to+ llidx leave then next ( line ) + else nip then ; +: llfind ( elem ll -- f ) + 0 to llidx 0 to llprev begin ( elem line ) + 2dup <> while + 1 to+ llidx dup to llprev + llnext dup while repeat then ( elem line ) + nip bool ; diff --git a/fs/tests/kernel.fs b/fs/tests/kernel.fs @@ -79,18 +79,6 @@ current .x 6 foo 209 #eq 20 foo 220 #eq -\ linked lists -0 value ll -4 &+@ myfield -here to ll 0 , 42 , -ll lladd drop 54 , -here 0 , 33 , to' ll llinsert -ll myfield 33 #eq -ll llnext myfield 42 #eq -ll llnext llnext myfield 54 #eq -ll llnext llnext ll llprev myfield 42 #eq -ll llcnt 3 #eq - \ Local variables : foo 54 >r 42 >r 1 to+ V1 2 to+ V2 V2 V1 rfree ; foo 55 #eq 44 #eq diff --git a/fs/tests/lib/all.fs b/fs/tests/lib/all.fs @@ -2,6 +2,7 @@ f<< /tests/lib/core.fs f<< /tests/lib/bit.fs f<< /tests/lib/str.fs +f<< /tests/lib/ll.fs f<< /tests/lib/struct.fs f<< /tests/lib/meta.fs f<< /tests/lib/context.fs diff --git a/fs/tests/lib/ll.fs b/fs/tests/lib/ll.fs @@ -0,0 +1,24 @@ +?f<< /tests/harness.fs +?f<< /lib/ll.fs +testbegin +\ linked lists +0 value ll +4 &+@ myfield +here to ll 0 , 42 , +ll lladd drop 54 , +here 0 , 33 , to' ll llinsert +ll myfield 33 #eq +ll llnext myfield 42 #eq +ll llnext llnext myfield 54 #eq +ll llcnt 3 #eq +2 ll llitern myfield 54 #eq +llidx 2 #eq +llprev myfield 42 #eq +4 ll llitern 0 #eq +llidx 3 #eq +llprev myfield 54 #eq +$1234 ll llfind not # +ll llnext ll llfind # +llidx 1 #eq +llprev myfield 33 #eq +testend diff --git a/fs/text/ed.fs b/fs/text/ed.fs @@ -1,6 +1,7 @@ ?f<< /lib/arena.fs ?f<< /lib/fmt.fs ?f<< /lib/str.fs +?f<< /lib/ll.fs : nspcs ( n -- ) ?dup if >r begin spc> next then ; @@ -11,11 +12,7 @@ struct[ Line : :range ( line -- a u ) dup ptr swap cnt ; - : :itern ( n line -- iter-n line ) - over not if exit then over >r \ V1=asked-n - swap >r begin ( line ) - dup llnext ?dup if nip else r> r> -^ swap exit then next ( line ) - r> swap ; + : :itern ( n line -- iter-n line ) llitern llidx swap ; ]struct extends IO struct[ Edbuf @@ -127,8 +124,10 @@ extends IO struct[ Edbuf : :dellines ( n self -- ) over not if 2drop exit then >r \ V1=self - >r V1 sel dup begin llnext dup not if leave then next ( delpoint tgt ) - tuck swap V1 to' lines llprev ( tgt tgt prev ) ! ( tgt ) + V1 sel V1 lines llfind drop llprev ( n delpoint ) + ?dup not if V1 to' lines then swap ( delpoint n ) + V1 sel llitern ( delpoint tgt ) + tuck swap ( tgt tgt prev ) ! ( tgt ) ?dup not if V1 lines llend then r> _sel! ; ]struct diff --git a/fs/xcomp/bootlo.fs b/fs/xcomp/bootlo.fs @@ -155,13 +155,8 @@ alias noop [then] alias @ llnext : llend ( ll -- lastll ) begin dup llnext ?dup while nip repeat ( ll ) ; -: llprev ( tgt ll -- prev ) - begin 2dup llnext = not while llnext ?dup while repeat - abort" llprev failed" then nip ; : llappend ( elem ll -- ) llend ! ; : lladd ( ll -- newll ) here swap llappend here 0 , ; -: llinsert ( elem ll -- ) over swap @! swap ! ; -: llcnt ( ll -- count ) 0 >r begin ?dup not if r> neg exit then llnext next ; \ Entry metadata -4 &+@ emeta