| \ A simple immplementation of the blocks wordset. |
\ A less simple implementation of the blocks wordset. |
| |
|
| \ This implementation uses only a single buffer and will therefore be a |
\ An more efficient implementation would use mmap on OSs that |
| \ little slow. An efficient implementation would use mmap on OSs that |
|
| \ provide it and many buffers on OSs that do not provide mmap. |
\ provide it and many buffers on OSs that do not provide mmap. |
| |
|
| |
\ Now, the replacement algorithm is "direct mapped"; change to LRU |
| |
\ if too slow. Using more buffers helps, too. |
| |
|
| \ I think I avoid the assumption 1 char = 1 here, but I have not tested this |
\ I think I avoid the assumption 1 char = 1 here, but I have not tested this |
| |
|
| \ 1024 constant chars/block \ mandated by the standard |
\ 1024 constant chars/block \ mandated by the standard |
| |
|
| create block-buffer chars/block chars allot |
require struct.fs |
| |
|
| |
struct |
| |
1 cells: field buffer-block \ the block number |
| |
1 cells: field buffer-fid \ the block's fid |
| |
1 cells: field buffer-dirty \ the block dirty flag |
| |
chars/block chars: field block-buffer \ the data |
| |
0 cells: field next-buffer |
| |
end-struct buffer-struct |
| |
|
| |
Variable block-buffers |
| |
Variable last-block |
| |
|
| |
$20 Value buffers |
| |
|
| |
User block-fid |
| |
|
| |
: block-cold |
| |
defers 'cold block-fid off last-block off |
| |
buffers buffer-struct drop * allocate throw dup block-buffers ! |
| |
buffers buffer-struct drop * erase ; |
| |
|
| variable buffer-block 0 buffer-block ! \ the block currently in the buffer |
' block-cold IS 'cold |
| variable block-fid 0 block-fid ! \ the file id of the current block file |
|
| variable buffer-dirty buffer-dirty off |
|
| |
|
| |
block-cold |
| |
|
| |
Defer flush-file |
| |
|
| |
: use-file ( addr u -- ) |
| |
block-fid @ IF flush-file block-fid @ close-file throw THEN |
| |
2dup r/w bin open-file 0<> |
| |
if |
| |
drop r/w bin create-file throw |
| |
else |
| |
nip nip |
| |
then |
| |
block-fid ! ; |
| |
|
| \ the file is opened as binary file, since it either will contain text |
\ the file is opened as binary file, since it either will contain text |
| \ without newlines or binary data |
\ without newlines or binary data |
| : get-block-fid ( -- fid ) |
: get-block-fid ( -- fid ) |
| block-fid @ 0= |
block-fid @ 0= |
| if |
if |
| s" blocks.fb" r/w bin open-file 0<> |
s" blocks.fb" use-file |
| if |
|
| s" blocks.fb" r/w bin create-file throw |
|
| then |
|
| block-fid ! |
|
| then |
then |
| block-fid @ ; |
block-fid @ ; |
| |
|
| 1- chars/block chars um* get-block-fid reposition-file throw ; |
1- chars/block chars um* get-block-fid reposition-file throw ; |
| |
|
| : update ( -- ) |
: update ( -- ) |
| buffer-dirty on ; |
last-block @ ?dup IF buffer-dirty on THEN ; |
| |
|
| : save-buffers ( -- ) |
: save-buffer ( buffer -- ) >r |
| buffer-dirty @ buffer-block @ 0<> and |
r@ buffer-dirty @ r@ buffer-block @ 0<> and |
| if |
if |
| buffer-block @ block-position |
r@ buffer-block @ block-position |
| block-buffer chars/block get-block-fid write-file throw |
r@ block-buffer chars/block r@ buffer-fid @ write-file throw |
| buffer-dirty off |
r@ buffer-dirty off |
| endif ; |
endif |
| |
rdrop ; |
| |
|
| |
: empty-buffer ( buffer -- ) |
| |
buffer-block off ; |
| |
|
| : empty-buffers ( -- ) |
: save-buffers ( -- ) block-buffers @ |
| 0 buffer-block ! ; |
buffers 0 ?DO dup save-buffer next-buffer LOOP drop ; |
| |
|
| |
: empty-buffers ( -- ) block-buffers @ |
| |
buffers 0 ?DO dup empty-buffer next-buffer LOOP drop ; |
| |
|
| : flush ( -- ) |
: flush ( -- ) |
| save-buffers |
save-buffers |
| empty-buffers ; |
empty-buffers ; |
| |
|
| |
' flush IS flush-file |
| |
|
| |
: get-buffer ( n -- a-addr ) |
| |
buffers mod buffer-struct drop * block-buffers @ + ; |
| |
|
| : block ( u -- a-addr ) |
: block ( u -- a-addr ) |
| dup 0= -35 and throw |
dup 0= -35 and throw |
| dup buffer-block @ <> |
dup get-buffer >r |
| |
dup r@ buffer-block @ <> |
| |
r@ buffer-fid @ block-fid @ <> and |
| if |
if |
| save-buffers |
r@ save-buffer |
| dup block-position |
dup block-position |
| block-buffer chars/block get-block-fid read-file throw |
r@ block-buffer chars/block get-block-fid read-file throw |
| \ clear the rest of the buffer if the file is too short |
\ clear the rest of the buffer if the file is too short |
| block-buffer over chars + chars/block rot - blank |
r@ block-buffer over chars + chars/block rot chars - blank |
| buffer-block ! |
r@ buffer-block ! |
| |
get-block-fid r@ buffer-fid ! |
| else |
else |
| drop |
drop |
| then |
then |
| block-buffer ; |
r> dup last-block ! block-buffer ; |
| |
|
| : buffer ( u -- a-addr ) |
: buffer ( u -- a-addr ) |
| \ reading in the block is unnecessary, but simpler |
\ reading in the block is unnecessary, but simpler |
| |
|
| User scr 0 scr ! |
User scr 0 scr ! |
| |
|
| |
: updated? ( n -- f ) scr @ buffer |
| |
[ 0 buffer-dirty 0 block-buffer - ] Literal + @ ; |
| |
|
| : list ( u -- ) |
: list ( u -- ) |
| \ calling block again and again looks inefficient but is necessary |
\ calling block again and again looks inefficient but is necessary |
| \ in a multitasking environment |
\ in a multitasking environment |
| dup scr ! |
dup scr ! |
| ." Screen " u. cr |
." Screen " u. |
| |
updated? 0= IF ." not " THEN ." modified " cr |
| 16 0 |
16 0 |
| ?do |
?do |
| i 2 .r space scr @ block i 64 * chars + 64 type cr |
i 2 .r space scr @ block i 64 * chars + 64 type cr |
| : +thru ( i*x n1 n2 -- j*x ) |
: +thru ( i*x n1 n2 -- j*x ) |
| 1+ swap 0 ?DO I +load LOOP ; |
1+ swap 0 ?DO I +load LOOP ; |
| |
|
| |
: --> ( -- ) refill drop ; immediate |
| |
|
| |
: block-included ( addr u -- ) |
| |
block-fid @ >r block-fid off use-file |
| |
1 load block-fid @ close-file throw flush |
| |
r> block-fid ! ; |
| |
|
| |
: include ( "name" -- ) |
| |
name 2dup dup 3 - /string s" .fb" compare |
| |
0= IF block-included ELSE included THEN ; |
| |
|
| get-current environment-wordlist set-current |
get-current environment-wordlist set-current |
| true constant block |
true constant block |
| true constant block-ext |
true constant block-ext |
| set-current |
set-current |
| |
|
| |
: bye ['] flush catch drop bye ; |