~vdupras/duskos

1024013264e4d4ce43099f4e2a4de4670c8191fb — binarycat a month ago 6ca68a5
filter subsystem redux

Here's my second attempt at this patch. "with'" has become "with" and the old "with" has been removed.
I found the code was more readable if I just used "to'", that way all the arguments were on the same side
of with.

I have added some more comments trying to explain how to use the system, hopefully this is good enough
for now.
6 files changed, 67 insertions(+), 0 deletions(-)

M fs/lib/str.fs
A fs/lib/with.fs
A fs/sys/filter.fs
M fs/tests/lib/all.fs
M fs/tests/lib/str.fs
A fs/tests/lib/with.fs
M fs/lib/str.fs => fs/lib/str.fs +13 -0
@@ 8,6 8,19 @@ $100 value STR_MAXSZ
\ "skip" str, that is, return the address following its last char
: s) ( str -- a ) c@+ + ;

\\ append character to end of string
: sappend ( c str -- ) tuck s) c! dup c@ 1+ swap c! ;

\\ checks if str1 contains all of str2 (is str2 a substring?)
: scontains ( str1 str2 -- f )
  >r c@+ begin
    dup r@ c@ >= while
    over r@ c@+ []= if
      r> drop 2drop 1 exit
    then
    1- swap 1+ swap
  repeat r> drop 2drop 0 ;

\ find active string in "list" and return its index, -1 if not found.
\ A list is a simple sequence of strings (length byte, then contents, then
\ another one...) ended by a 0 length

A fs/lib/with.fs => fs/lib/with.fs +3 -0
@@ 0,0 1,3 @@
\\ helper word to save and restore a variable across a function call.
: with ( w u addr -- ) dup >r dup @ >r ! execute r> r> ! ;


A fs/sys/filter.fs => fs/sys/filter.fs +36 -0
@@ 0,0 1,36 @@
\ filter executes a word and filters its output based on a substring match.
\ it parses first the word to execute, the the substring search to filter
\ the output by.

?f<< lib/str.fs
?f<< lib/with.fs

SPC value filter-delim

\ internal state
create filter-buf $100 allot
0 value filter-str
alias abort filter-out

: filter-chunk
  filter-buf filter-str scontains if
      filter-buf ['] stype to' filter-out @ to' emit with
      filter-delim filter-out
    then
    0 filter-buf c! ;

: filter-char ( c -- )
  dup filter-delim = if drop
    filter-chunk
  else
    filter-buf sappend
  then ;

: with-filter-str ( w str -- )
  \ TODO: replace emit with stdout when it is added
  to filter-str
  0 filter-buf c!
  to' emit @ to filter-out
  ['] filter-char to' emit with filter-chunk ;

: filter ( "word" "query" -- ) ' word with-filter-str ;

M fs/tests/lib/all.fs => fs/tests/lib/all.fs +1 -0
@@ 3,3 3,4 @@ f<< tests/lib/core.fs
f<< tests/lib/str.fs
f<< tests/lib/xdict.fs
f<< tests/lib/struct.fs
f<< tests/lib/with.fs

M fs/tests/lib/str.fs => fs/tests/lib/str.fs +5 -0
@@ 15,4 15,9 @@ S" baz" list sfind -1 #eq
'0' A-Za-z? not #
'z' alnum? #
'0' alnum? #

S" foobar" S" foo" scontains #
S" foobar" S" bar" scontains #
S" foobar" S" oba" scontains #
S" foobar" S" baz" scontains not #
testend

A fs/tests/lib/with.fs => fs/tests/lib/with.fs +9 -0
@@ 0,0 1,9 @@
?f<< lib/with.fs
?f<< tests/harness.fs
testbegin
\ testing lib/with
create cell1 7 ,
: foo cell1 @ 55 #eq ;
: bar ['] foo 55 cell1 with ;
bar cell1 @ 7 #eq
testend