pfe-useful-ext ? Useful kernel extensions
_like:COMPILE, ?=>? ( | ) ; | ? |
"EXTENSIONS"
;($ ( [word] -- cs-token ) ?=>? ( | ) ; | ? |
"EXTENSIONS"
;) ( cs-token -- ) ?=>? ( | ) ; | ? |
"EXTENSIONS"
;PFE-PRINTF ( args ... format$ -- ) ?=>? ( | ) ; | ? |
"EXTENSIONS"
;PFE-SPRINTF ( args ... format$ dest$ -- len-dest ) ?=>? ( | ) ; | ? |
"EXTENSIONS"
;LOADF ( "filename" -- ) ?=>? ( | ) ; | ? |
"EXTENSIONS"
;DOER ( word -- ) ?=>? ( | ) ; | ? |
"EXTENSIONS"
;MAKE ( [word] -- ) ?=>? ( | ) ; | ? |
"EXTENSIONS"
;;AND ( -- ) ?=>? ( | ) ; | ? |
"EXTENSIONS"
;[NOT] ( a -- a' ) ?=>? ( | ) ; | ? |
"EXTENSIONS"
;+FIELD: ( offset "name" -- offset ) ?=>? ( | ) ; | ? |
"EXTENSIONS"
;/FIELD ( offset size "name" -- offset+size ) ?=>? ( | ) ; | ? |
"EXTENSIONS"
;REPLACE-IN ( to-xt from-xt n "name" -- ) ?=>? ( | ) ; | ? |
"EXTENSIONS"
;(LOADF-LOCATE) ( xt -- nfa ) ?=>? ( | ) ; | ? |
"EXTENSIONS"
;LOADF-LOCATE ( "name" -- ) ?=>? ( | ) ; | ? |
"EXTENSIONS"
;X" ( "hex-q" -- bstring ) ?=>? ( | ) ; | ? |
"EXTENSIONS"
;EVALUATE-WITH ( i*x addr len xt[i*x--j*x] -- j*x ) ?=>? ( | ) ; | ? |
"EXTENSIONS"
;[POSSIBLY] ( [name] -- ?? ) ?=>? ( | ) ; | ? |
"EXTENSIONS"
;[VOCABULARY] ( "name" -- ) ?=>? ( | ) ; | ? |
"EXTENSIONS"
;[DEF] ( -- ) ?=>? ( | ) ; | ? |
"EXTENSIONS"
;CONTEXT? ( -- number ) ?=>? ( | ) ; | ? |
"EXTENSIONS"
;CASE-SENSITIVE-VOC ( -- ) ?=>? ( | ) ; | ? |
"EXTENSIONS"
;DEFS-ARE-CASE-SENSITIVE ( -- ) ?=>? ( | ) ; | ? |
"EXTENSIONS"
;DEFS-ARE-SEARCHED-ALSO ( -- ) ?=>? ( | ) ; | ? |
"EXTENSIONS"
;!USE ( -- true ) * a synonym for => TRUE !USE SMART-WORDS!
_like:COMPILE, - no description, sorry
($ ( [word] -- cs-token ) compile-only => "EXTENSIONS"
takes the execution token of the following word and
saves it on the compile-stack. The correspondig closing
)
will then feed it into >COMPILE
- so this pair
of word provides you with a prefix-operation syntax
that you may have been seen in lisp-like languages.
($ IF ($ 0= A1 @ )) ($ THEN ." hello " )
Note that an opening simple (
paren is a comment.
) ( cs-token -- ) => "EXTENSIONS"
takes the execution-token from (\$
and compiles
it using >COMPILE
PFE-PRINTF ( args ... format$ -- ) => "EXTENSIONS"
uses SPRINTF
to print to a temporary 256-char buffer
and prints it to stdout afterwards. See the example
at SPRINTF
of what it does internally.
PFE-SPRINTF ( args ... format$ dest$ -- len-dest ) => "EXTENSIONS"
just like the standard sprintf() function in C, but the format is a counted string and accepts %#s to be the format-symbol for a forth-counted string. The result is a zeroterminated string at dest$ having a length being returned. To create a forth-counted string, you could use:
variable A 256 ALLOT 15 " example" " the %#s value is %i" A 1+ SPRINTF A C! A COUNT TYPE
LOADF ( "filename" -- ) => "EXTENSIONS"
loads a file just like INCLUDE
but does also put
a MARKER
in the LOADED
dictionary that you can
do a FORGET
on to kill everything being loaded
from that file.
DOER ( word -- ) => "EXTENSIONS"
In PFE it is a synonym to DEFER
which a semistandard word.
Unlike DEFER
, the DOER
-vector was set with an a small
piece of code between MAKE
and ;AND
. The "DOER"-word
should be replaced with DEFER
IS
, which is easy since
the DEFER
and DOER
point to the same internal runtime.
MAKE ( [word] -- ) ... ;AND => "EXTENSIONS"
make a seperated piece of code between MAKE
and ;AND
and on execution of the MAKE
the named word is twisted
to point to this piece of code. The word is usually
a DOER
but the current implementation works
on DEFER
just as well, just as it does on other words who
expect to find an execution-token in its PFA. You could even
create a colon-word that starts with NOOP
and can then make
that colon-word be prefixed with the execution of the code piece.
This MAKE
does even work on LOCALS|
and VAR
but it is uncertain
what that is good for.
;AND ( -- ) => "EXTENSIONS"
For the code piece between MAKE
and ;AND
, this word
will do just an EXIT
. For the code outside of
the MAKE
construct a branch-around must be resolved then.
[NOT] ( a -- a' ) => "EXTENSIONS"
executes 0=
but this word is immediate so that it does
affect the cs-stack while compiling rather than compiling
anything. This is useful just before words like [IF]
to
provide semantics of an [IFNOT]
. It is most useful in
conjunction with "=> [DEFINED] word" as it the sequence
"[DEFINED] word [NOT] [IF]
" can simulate "[IFNOTDEF] word
"
+FIELD: ( offset "name" -- offset ) => "EXTENSIONS"
created a new name with an OFFSET-RT
runtime using the given offset.
Leave the offset-value untouched, so it can be modified with words
like CHAR+
and CELL+
and SFLOAT+
; This word is the simplest way
to declared structure access words in forth - the two STRUCT
modules
contain a more elaborate series of words. Use this one like:
0 ( a fresh definition is started ) +FIELD: zapp.a+ CHAR+ ( zero offset from the base of the struct ) +FIELD: zapp.b+ CELL+ ( no alignment, starts off at 1 from base ) +FIELD: zapp+ DROP ( store size of complete zap structure ) 0 zapp+ ( extend the zap structure ) +FIELD: zappx.c+ CELL+ ( a new field ) +FIELD: zappx+ DROP ( and save it again ) CREATE zapp1 0 zapp+ ALLOT ( a way to allocate a strucutre ) zapp2 zapp.b+ @ ( read a value from the field ) 16 zapp2 zapp.b+ ! ( store a value in there )
this form is not the traditional form used in forth, it is however
quite simple. Use the simplefield declaration with /FIELD
to
be compatible with traditional styles that build on top of sizeof
constants in forth (which are not part of the ANS Forth standard).
/FIELD ( offset size "name" -- offset+size ) => "EXTENSIONS"
created a new +FIELD
name with an OFFSET-RT
of offset. Then add the size value to the offset so that
the next /FIELD
declaration will start at the end of the
field currently declared. This word is the simplest way to
declared structure access words in forth - the two STRUCT
modules
contain a more elaborate series of words. This one is used like:
0 ( a fresh definition is started ) /CHAR /FIELD ->zapp.a ( zero offset from the base of the struct ) /CELL /FIELD ->zapp.b ( no alignment, starts off at 1 from base ) CONSTANT /zapp ( store size of complete zap structure ) /zapp ( extend the zap structure ) /CELL /FIELD ->zappx.c ( a new field ) CONSTANT /zappx ( and save it again ) CREATE zapp1 /zapp ALLOT ( a way to allocate a strucutre ) /zapp BUFFER: zapp2 ( another way to do it, semi-standard ) zapp2 ->zapp.b @ ( read a value from the field ) 16 zapp2 ->zapp.b ! ( store a value in there )
compare also with /CHAR
/WCHAR
/CELL
/DCELL
and use +FIELD
as the lowlevel word, can simulate as
: /FIELD SWAP +FIELD + ;
REPLACE-IN ( to-xt from-xt n "name" -- ) => "EXTENSIONS"
will handle the body of the named word as a sequence of cells (or tokens) and replaces the n'th occurences of from-xt into to-xt. A negative value will change all occurences. A zero value will not change any.
(LOADF-LOCATE) ( xt -- nfa ) => "EXTENSIONS"
the implementation of LOADF-LOCATE
LOADF-LOCATE ( "name" -- ) => "EXTENSIONS"
look for the filename created by LOADF
that had been
defining the given name. LOADF
has created a marker
that is above the INCLUDED
file and that
marker has a body-value just below the
INCLUDED
file. Hence the symbol was defined during
LOADF
execution of that file.
: LOADF-LOCATE ?EXEC POSTPONE ' (LOADF-LOCATE) .NAME ;
X" ( "hex-q" -- bstring ) => "EXTENSIONS"
places a counted string on stack containing bytes specified by hex-string - the hex string may contain spaces which will delimit the bytes
example: X" 41 42 4344" COUNT TYPE ( shows ABCD )
EVALUATE-WITH ( i*x addr len xt[i*x--j*x] -- j*x ) => "EXTENSIONS"
added to be visible on the forth command line on request by MLG, he has explained the usage before a lot, you can get an idea from:
: EVALUATE ['] INTERPRET EVALUATE-WITH ;
The word is used internally in PFE for the loadlist evaluation of
the binary modules: where previously each loadercode had its own
CREATE-execution we do now call the original forthish CREATE-word
like, so bootstrapping a VARIABLE
will now call VARIABLE itself
and of course we need to set up the TIB-area to point to the name
of the variable that shall be created in the forth dictionary:
: LOAD-WORD ( arg-value str-ptr str-len loader-code -- ) CASE #LOAD-VARIABLE OF ['] VARIABLE EVALUATE-WITH ENDOF .... ENDCASE CLEARSTACK ;
[POSSIBLY] ( [name] -- ?? ) => "EXTENSIONS"
check if the name exists, and execute it immediatly if found. Derived from POSSIBLY as seen in other forth systems.
: [POSSIBLY] (') ?DUP IF EXECUTE THEN ; IMMEDIATE
[VOCABULARY] ( "name" -- ) => "EXTENSIONS"
create an immediate vocabulary. Provides for basic modularization.
: [VOCABULARY] VOCABULARY IMMEDIATE ;
[DEF] ( -- ) => "EXTENSIONS"
immediatly set topmost CONTEXT
voc to CURRENT
compilation voc.
: DEF' CURRENT @ CONTEXT ! ; IMMEDIATE
note that in PFE most basic vocabularies are immediate, so that you can use a sequence of
FORTH ALSO DEFINITIONS [DEF] : GET-FIND-3 [ANS] ['] FIND [FIG] ['] FIND [DEF] ['] FIND ;
where the first wordlist to be searched via the search order are [ANS] and [FIG] and FORTH (in this order) and which may or may not yield different flavours of the FIND routine (i.e. different XTs)
CONTEXT? ( -- number ) => "EXTENSIONS"
GET-CONTEXT and count how many times it is in the order but the CONTEXT variable itself. The returned number is therefore minus one the occurences in the complete search-order. usage:
ALSO EXTENSIONS CONTEXT? [IF] PREVIOUS [THEN] ALSO DEF' DEFAULT-ORDER : CONTEXT? 0 LVALUE _count GET-ORDER 1- SWAP LVALUE _context 0 ?DO _context = IF 1 +TO _count THEN LOOP _count ;
CASE-SENSITIVE-VOC ( -- ) => "EXTENSIONS"
accesses CONTEXT
which is generally the last named VOCABULARY
.
sets a flag in the vocabulary-definition so that words are matched
case-sensitive.
example: VOCABULARY MY-VOC MY-VOC CASE-SENSITIVE-VOC
OBSOLETE! use DEFS-ARE-CASE-SENSITIVE
DEFS-ARE-CASE-SENSITIVE ( -- ) => "EXTENSIONS"
accesses CURRENT
which is generally the last wordlist that the
DEFINITIONS
shall go in. sets there a flag in the vocabulary-definition
so that words are matched case-sensitive.
example: VOCABULARY MY-VOC MY-VOC DEFINITIONS DEFS-ARE-CASE-SENSITIVE
DEFS-ARE-SEARCHED-ALSO ( -- ) => "EXTENSIONS"
binds CONTEXT
with CURRENT
. If the CURRENT
VOCABULARY
is in
the search-order (later), then the CONTEXT
vocabulary will
be searched also. If the result of this word could lead into
a recursive lookup with FIND
it will throw CURRENT_DELETED
and leave the CURRENT
VOCABULARY
unaltered.
example:
MY-VOC DEFINITIONS MY-VOC-PRIVATE DEFS-ARE-SEARCHED-ALSO